diff --git a/.cursor/rules/roblox/common/navigation/avatar/guides.yaml b/.cursor/rules/roblox/common/navigation/avatar/guides.yaml index 4aaea1f4..1d73a73d 100644 --- a/.cursor/rules/roblox/common/navigation/avatar/guides.yaml +++ b/.cursor/rules/roblox/common/navigation/avatar/guides.yaml @@ -55,6 +55,8 @@ navigation: section: - title: Overview path: /art/characters/facial-animation/ + - title: Validation process + path: /art/characters/head-validation - title: Head specifications path: /art/characters/head-specifications - title: Face cage optimizations diff --git a/.cursor/rules/roblox/common/navigation/engine/guides.yaml b/.cursor/rules/roblox/common/navigation/engine/guides.yaml index 3e5c517f..5508291c 100644 --- a/.cursor/rules/roblox/common/navigation/engine/guides.yaml +++ b/.cursor/rules/roblox/common/navigation/engine/guides.yaml @@ -179,8 +179,8 @@ navigation: path: /workspace/collisions - title: Raycasting path: /workspace/raycasting - # - title: Bézier Curves - # path: /docs/mechanics/bezier-curves + - title: Model generation + path: /parts/model-generation - title: Scripting path: /scripting/ section: diff --git a/.cursor/rules/roblox/common/navigation/monetize.yaml b/.cursor/rules/roblox/common/navigation/monetize.yaml index a7c139f8..402dee17 100644 --- a/.cursor/rules/roblox/common/navigation/monetize.yaml +++ b/.cursor/rules/roblox/common/navigation/monetize.yaml @@ -46,19 +46,15 @@ navigation: path: /ip-licensing/glossary - title: Advertise - path: /production/promotion/ads-manager + path: /production/promotion/advertise section: - title: Ads Manager path: /production/promotion/ads-manager - - title: Reporting and billing - path: /production/promotion/reporting-and-billing - title: Roblox-served ads vs. independent ads path: /production/promotion/advertise-on-roblox - title: Immersive ads path: /production/monetization/immersive-ads - title: Rewarded video ads path: /production/promotion/rewarded-video-ads - - title: Search ads - path: /production/promotion/search-ads - title: Advertising standards path: /production/promotion/comply-with-advertising-standards diff --git a/.cursor/rules/roblox/en-us/art/accessories/caging-best-practices.md b/.cursor/rules/roblox/en-us/art/accessories/caging-best-practices.md index fef5dda8..8e34e161 100644 --- a/.cursor/rules/roblox/en-us/art/accessories/caging-best-practices.md +++ b/.cursor/rules/roblox/en-us/art/accessories/caging-best-practices.md @@ -3,7 +3,7 @@ title: Caging best practices description: In-depth description and images of various caging best practices for layered clothing. --- - +

Caging is a complex process required to define the inner and outer surface of a layered clothing item. Properly caged assets allow your clothing items to stretch and layer in combination with each other. Cages that are improperly configured can lead to cosmetic issues with the look and feel of your clothing item. diff --git a/.cursor/rules/roblox/en-us/art/accessories/clothing-specifications.md b/.cursor/rules/roblox/en-us/art/accessories/clothing-specifications.md index 074cfcbd..f3fc717b 100644 --- a/.cursor/rules/roblox/en-us/art/accessories/clothing-specifications.md +++ b/.cursor/rules/roblox/en-us/art/accessories/clothing-specifications.md @@ -174,7 +174,7 @@ Assets with invalid cage configurations may fail validation and are subject to m For a basic overview on caging, see the [Basic Clothing Tutorial](../accessories/creating/caging-setup.md) and the relevant section of the tutorial video at [8:32](https://www.youtube.com/watch?v=C-DwGRBHvmE&t=512s): - + #### Inner Cage diff --git a/.cursor/rules/roblox/en-us/art/accessories/creating-rigid/index.md b/.cursor/rules/roblox/en-us/art/accessories/creating-rigid/index.md index 4f1e0719..294b181f 100644 --- a/.cursor/rules/roblox/en-us/art/accessories/creating-rigid/index.md +++ b/.cursor/rules/roblox/en-us/art/accessories/creating-rigid/index.md @@ -4,7 +4,7 @@ description: This tutorial covers the basic steps required to publish a custom a next: /art/accessories/creating-rigid/modeling-setup --- - +

Rigid accessories are 3D objects that users can equip to their avatar characters in an experience or through Roblox's [Marketplace](https://www.roblox.com/catalog) and [Avatar Editor](https://www.roblox.com/my/avatar). diff --git a/.cursor/rules/roblox/en-us/art/accessories/creating-rigid/publishing.md b/.cursor/rules/roblox/en-us/art/accessories/creating-rigid/publishing.md index af7e3823..9dbe8abc 100644 --- a/.cursor/rules/roblox/en-us/art/accessories/creating-rigid/publishing.md +++ b/.cursor/rules/roblox/en-us/art/accessories/creating-rigid/publishing.md @@ -41,6 +41,6 @@ You can check your accessory's moderation status in the [Creator Hub](https://cr After moderation completes, your item's publishing details become available to edit and enable for sale. See the following for an overview on the various sale options available: - +
After listing an asset to the Marketplace, you can return to this page to edit your item's sale details, or take the item offsale. diff --git a/.cursor/rules/roblox/en-us/art/accessories/creating/index.md b/.cursor/rules/roblox/en-us/art/accessories/creating/index.md index f2634801..fb3a3ae1 100644 --- a/.cursor/rules/roblox/en-us/art/accessories/creating/index.md +++ b/.cursor/rules/roblox/en-us/art/accessories/creating/index.md @@ -4,7 +4,7 @@ description: This tutorial covers the basic steps required in Blender to Studio- next: /art/accessories/creating/modeling-setup --- - +

You can create your own custom avatar clothing using Blender and Roblox's downloadable project templates. These project templates include [components required for layered clothing](../../../art/accessories/layered-clothing.md#components-of-a-layered-clothing-accessory), and can double as a mannequin to quickly begin shaping and sculpting your clothing assets. By the end of this tutorial, you will have a clothing asset that contains all the required components for a layered clothing accessory on the Marketplace. diff --git a/.cursor/rules/roblox/en-us/art/accessories/from-existing.md b/.cursor/rules/roblox/en-us/art/accessories/from-existing.md index 1a1b758d..b48de931 100644 --- a/.cursor/rules/roblox/en-us/art/accessories/from-existing.md +++ b/.cursor/rules/roblox/en-us/art/accessories/from-existing.md @@ -187,7 +187,7 @@ After generating your `Class.Accessory` item, you can now begin the process of * For additional information and instructions on this process, see [uploading and publishing instructions](../../marketplace/publish-to-marketplace.md). - +
You now have your accessory added to the Marketplace catalog! Use the item's Marketplace link to view your listing at any time, or to send to your connections and followers for additional engagement. diff --git a/.cursor/rules/roblox/en-us/art/characters/facial-animation/index.md b/.cursor/rules/roblox/en-us/art/characters/facial-animation/index.md index 640f6aba..d96dfd55 100644 --- a/.cursor/rules/roblox/en-us/art/characters/facial-animation/index.md +++ b/.cursor/rules/roblox/en-us/art/characters/facial-animation/index.md @@ -20,6 +20,15 @@ When creating heads intended for the Marketplace, ensure that your head meets Ro Using third-party modeling tools, you can either modify a rigged character model to meet head requirements, or create a head from scratch. For step-by-step instructions on how to add face bones, apply skinning, posing, and mapping poses on a head model in Blender, see [Create basic heads](../../../art/characters/facial-animation/create-basic-heads.md). This guide includes several reference files you can use to compare and track your progress. +### Resources + +Heads designated for the Marketplace require specific components to ensure universal support across Roblox's platform. Heads are often the most complex part of an avatar character. Use the following docs to best equip your assets to pass validation and work well with other assets: + +- Understand how Roblox tests facial animations in the [validation process](../head-validation.md) and learn common issues that you can self-resolve. +- Similar to character bodies and clothing, Marketplace heads must also follow [Roblox's specifications](../head-specifications.md). +- Ensure that you are following Roblox's [head caging best practices](../face-caging-best-practices.md) to ensure the best results for clothing, validation, and makeup. +- Use the [FACS poses reference](../../../art/characters/facial-animation/facs-poses-reference.md) when posing and mapping your head. + ## Create face accessories Similar to creating heads, you can design and model face accessories using a third-party modeling software and import the models as a cosmetic `Class.Accessory` in Studio. When created correctly, equipped accessories stretch and deform as the head animates and emotes. @@ -36,7 +45,3 @@ If you're interested in animating a head, for use in-experience or to further te - -## Additional resources - -Heads are often the most complex part of an avatar character. Ensure that you are following Roblox's [head caging best practices](../face-caging-best-practices.md) and verify your FACS poses using the [FACS poses reference](../../../art/characters/facial-animation/facs-poses-reference.md). diff --git a/.cursor/rules/roblox/en-us/art/characters/head-comparison.md b/.cursor/rules/roblox/en-us/art/characters/head-comparison.md index f567ee36..4d601909 100644 --- a/.cursor/rules/roblox/en-us/art/characters/head-comparison.md +++ b/.cursor/rules/roblox/en-us/art/characters/head-comparison.md @@ -5,68 +5,308 @@ description: The Avatar Validation Tool checks for common character model issues The following table compares the classic decals with the dynamic head equivalent. + +The references below are not final and are subject to change. We encourage you to provide feedback on specific heads on the [DevForum announcement](https://devforum.roblox.com/t/completing-the-dynamic-head-migration/4301387). + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Asset Name
Classic
Dynamic
ClassicDynamic
**:3**
**Angelic**
**Bacon Face**
**Bandage**
**Beast Mode**
**Bling**
**Blue Eyeroll**
**Blue Galaxy Gaze**
**Blue Rock Star Smile**
**Camoface**
**Cat Eye - Zara Larsson**
**Classic Vampire**
**Country Morning**
**Crimson Laser Vision**
**Crimson Starface**
**Daring Beard**
**Devil Nas X - Lil Nas X LNX**
**\$.\$**
**Drooling Noob**
**Emerald Archfey Visage**
**Emerald Laser Vision**
**Emperor**
**Finn McCool**
**Friendly Grin**
**Golden Bling Braces**
**Golden Lightning Speaker**
**Golden Shiny Teeth**
**Green Amazeface**
**Green Drool Angry Zombie**
**Green Glowing Eyes**
**Green Ultimate Dragon Face**
**Green Whatchoo Talkin Bout**
**Its Go Time**
**Madbot 10000**
**Mr Bubbles**
**Optimist**
**Paintball Enthusiast**
**Pieface Jellyfreckles**
**Poisonous Beast Mode**
**Prankster**
**Puck**
**Purple Trance**
****Raig Face****
****Really Embarrassed****
****Red Glowing Eyes****
****Red Lip - Tate McRae****
****Rudolph****
****Sad Clown****
****Sapphire Laser Vision****
****Squiggle Mouth****
****Super Happy Joy****
****Teal Rock Star Smile****
**The Dog Whisperer**
**The First Time I Ever Played ROBLOX**
**Torque the Green Orc**
**Trance**
**Troublemaker**
**\$.\$**
**-_-**
**8-Bit Heart Face**
**:-/**
**:-[**
**:-o**
**:/**
**:3**
**:]**
**:D**
**:P**
**=)**
**>:3**
**>_<**
**^_^**
**Adorable Puppy**
**Alien**
**Alien Ambassador**
**Alright**
**Amelia Face**
**And then we'll take over the world!**
**Angry Zombie**
**Anguished**
**Anime Surprise**
**Award-Winning Smile**
**Awesome Face**
**Awkward Eyeroll**
**Awkward Grin**
**Awkward....**
**Bad Dog**
**Beaming with Pride**
**Beast Mode**
**Big Grin - Tai Verdes**
**Big Sad Eyes**
**BiteyMcFace**
**Blerg!**
**Blinky**
**Blizzard Beast Mode**
**Blue Amazeface**
**Blue Bubble Trouble**
**Blue Goof**
**Blue Rock Star Smile**
**Blue Starface**
**Blue Starry Sight**
**Blue Ultimate Dragon Face**
**Bluffing**
**Bombo Face**
**Bored**
**Braces**
**Bubble Trouble**
**Butterfly Wink - Lil Nas X (LNX)**
**Cat Eye - Zara Larsson**
**Check It**
**Cheerful Grin**
**Cheerful Hello**
**Chill**
**Chill McCool**
**Chubs**
**City Life Man - Face**
**City Life Woman - Face**
**Claire's Face**
**Classic Alien Face**
**Classic Female - Face**
**Classic Female v2 - Face**
**Classic Goof**
**Classic Male - Face**
**Classic Male v2 - Face**
**Classic Vampire**
**Commando**
**Concerned**
**Crazy Happy**
**Crazybot 10000**
**Crimson Evil Eye**
**Cuckookrazybot 10000**
**Cute Kitty**
**Cutiemouse**
**D:**
**D=**
**Daring**
**Daring Beard**
**Demented Mouse**
**Desert Commando**
**Devil Nas X - Lil Nas X (LNX)**
**Devilish Smile - 24kGoldn**
**Dex's Face**
**Diamond Grill - Lil Nas X (LNX)**
**Disbelief**
**Dizzy Face**
**Downcast**
**Drill Sergeant**
**Drool**
**Drooling Noob**
**Emerald Evil Eye**
**Err...**
**Exclamation Face**
**eXtreme**
**Eyes of Everflame**
**Eyes of Everfrost**
**Fang**
**Fast Car**
**Fearless**
**Finn McCool**
**Freckles**
**Friendly Cyclops**
**Friendly Grin**
**Friendly Pirate**
**Friendly Smile**
**Ghostface**
**Gigglypuff**
**Glee**
**Glittering Eye - Zara Larsson**
**Glory on the Gridiron**
**Gold Mermaid Visage**
**Golden Evil Eye**
**Golden Eyes - 24kGoldn**
**Golden Shiny Teeth**
**Good Intentioned**
**Goofball**
**Green Amazeface**
**Green Bubble Trouble**
**Green Goof**
**Green Starface**
**Green Starry Sight**
**Green Trance**
**Green Ultimate Dragon Face**
**Green Wistful Wink**
**Green-eyed Awesome Face**
**Gritty Bombo**
**Grr!**
**Happy :D**
**Happy Girl Face**
**Happy Wink**
**Heeeeeey...**
**Hilarious**
**Hmmm...**
**Hold It In**
**Huh?**
**Hut Hut Hike!**
**Hypnoface**
**I <3 New Site Theme**
**I Am Not Amused**
**I Didn't Eat That Cookie**
**I Hate Noobs**
**I wuv u**
**It's Go Time!**
**Jack Frost Face**
**Joyful Smile**
**Joyous Surprise**
**Just Trouble**
**Know-It-All Grin**
**Krezak - Face**
**Lady Lashes**
**Laughing Fun**
**Lavender Amazeface**
**Lazy Eye**
**Lightning Speaker**
**Lin's Face**
**Look At My Nose**
**Love**
**Manicbot 10000**
**Manlier Face**
**McLaren Big Grin**
**Meanie**
**Meow?**
**Monarch Butterfly Smile**
**Monster Face**
**Monster Smile**
**Mr. Toilet - Face**
**Mysterious**
**Neoclassic Male v2 - Face**
**Nervous**
**NetHack Addict**
**Not sure if...**
**Nouveau George**
**O.o**
**O_o**
**Obvious Wink**
**Oh Deer**
**Old Timer**
**Orange Starface**
**Overjoyed Smile**
**Pink Galaxy Gaze**
**Pink Mermaid Princess**
**Pink Shades McCool**
**Pink Wistful Wink**
**Poisonous Beast Mode**
**Prideful Smile**
**Puck**
**Pumpkin Face**
**Punk Face**
**Purple Bubble Trouble**
**Purple Butterfly Smile**
**Purple Mermaid Princess**
**Purple Moonstruck**
**Purple Wistful Wink**
**Pwnda Face**
**Radioactive Beast Mode**
**Raig Face**
**RAWR!**
**Red Goof**
**Red Lip - Tate McRae**
**Red Ultimate Dragon Face**
**Red White and Starface**
**Retro Smiley**
**ROAR!!!**
**Robot Smile**
**Rodeo Vampire - Lil Nas X (LNX)**
**Rogueish Good Looks**
**Rose Amazeface**
**Ruby Archfey Visage**
**Sad**
**Sadfaic**
**Sapphire Evil Eye**
**Scarecrow**
**Scarecrow Face**
**Secret Service**
**Semi Colon Open Paren**
**Serena’s Face**
**Serious Scar Face**
**Sharpnine's Face of Disappointment**
**Shocked**
**Sick Day**
**Sigmund**
**Silence**
**Silly Fun**
**Silver Punk Face**
**Singing**
**Sinister**
**Slickfang**
**Slithering Smile**
**Sly Guy Face**
**Smil Nas X - Lil Nas X (LNX)**
**Smiling Girl**
**Smith McCool**
**Smug**
**Sneaky Steve**
**Sniffles**
**So Funny**
**So Super Excited - Blue**
**So Super Excited - Pink**
**Sparkle Time Sparkle Eyes**
**Spring Bunny**
**Square Eyes**
**Squiggle Mouth**
**Squinty Assassin Face**
**Stare**
**Starface**
**Stink Eye**
**Stitchface**
**Sunny Fun**
**Sunrise Eyes - Tai Verdes**
**Super Happy Joy**
**Suspicious**
**Sweat It Out**
**Tango**
**The Big Dog**
**The Friendly Eviscerator**
**The Winning Smile**
**Thinking**
**Tiger Chase Fear Face**
**Tired Face**
**Tohru: The Phantom Claw's Face**
**Too Much Candy**
**Toothless**
**Toothy Grin**
**Torque the Blue Orc**
**Torque the Green Orc**
**Uh Oh**
**Up To Something**
**Vampire**
**Vans Checkerboard Blue Eyes**
**Violet Fang**
**Violet Starry Sight**
**Visual Studio Seized Up For 45 Seconds... Again**
**Walk the Plank You Scurvy Dogs!**
**WHAAAaaa!**
**Whistle**
**Wink-Blink**
**Winky**
**Winning Smile**
**Woman Face**
**Wonder Woman's Golden Armor - Face**
**XD**
**XD 2.0**
**Xtreme Happy**
**YAAAWWN.**
**Yawn**
**Yellow Starface**
**You ated my caik!**
**Zoey Face**
**Zombie Face**
**¬_¬**
**¬_¬ 2.0**
diff --git a/.cursor/rules/roblox/en-us/art/characters/head-specifications.md b/.cursor/rules/roblox/en-us/art/characters/head-specifications.md index e163e99e..37a86550 100644 --- a/.cursor/rules/roblox/en-us/art/characters/head-specifications.md +++ b/.cursor/rules/roblox/en-us/art/characters/head-specifications.md @@ -10,18 +10,12 @@ This content is for creators who intend to create character heads designated for Character models designed to be sold on the Marketplace require a specific set of components and configuration standards to ensure all avatar features work as expected. The following guidance applies to character model heads to ensure universal support for head accessories and facial animations. -For information on character body requirements, see [character specifications](./specifications.md). +Validation for heads use a specialized process that may require adjustment of your existing head asset. For more information, see [validation process](./head-validation.md). -To pass Marketplace validation, a dynamic head requires: - -1. A configured [head cage](#head-cage), with distinct eye and mouth landmarks. -2. [FACS controls](#facs-animation) to enable basic facial movements. - -Validation verifies that landmarks on the head mesh, denoted by the cage projections, must deform correctly when facial animation is applied for the basic movement tests. - -## Auto-setup recommendation - + +Auto-setup recommendation +
[Avatar auto-setup](../../avatar-setup/auto-setup.md) is an automated tool that automatically generates components for your avatar character, **including the head cage and facial animation** required for Marketplace character models. You can save time by submitting character models without avatar components into the auto-setup tool and modifying the output. You can test and refine your auto-setup output by using the Avatar setup tool previews. You can even download your output as a `.gltf` and adjust the FACS or cage data in your DCC tools. @@ -29,9 +23,14 @@ You can test and refine your auto-setup output by using the Avatar setup tool pr You can alternatively manually modify your own cages and FACS animations within your DCC tools, which may require more time or additional iteration in your workflow, such as weight-painting adjustments, to ensure it meets Marketplace policies. To submit issues or feedback regarding the avatar auto setup tool, submit a [bug report](https://devforum.roblox.com/c/bug-reports/10). +
## Head cage + +The head cage is used to verify animations during validation. see [validation process](./head-validation.md). + + Similar to other avatar body parts, an outer cage is required for the head. [High-quality cages](#caging-quality) ensure accessories and clothing items fit properly over the head. Head cages also serves to establish [facial landmarks](#facial-landmarks) for the eyes and mouth of the face for animation validation. ### Caging quality @@ -40,7 +39,7 @@ For details on improving the quality of your head cage, see [Face cage optimizat ### Facial landmarks -During validation, Roblox projects the cage eye/mouth regions to the base mesh to identify the eyes and mouth regions of your character head. These landmarks on the base mesh are used to track the correct deformations of your head when testing for the [minimum FACS poses](#facs-animation). +During validation, Roblox projects the cage eye/mouth regions to the base mesh to identify the eyes and mouth regions of your character head. Even for non-humanoid faces that don't include visual eyes or mouths, it's important to ensure that these landmarks still exist and can be projected over your base mesh. For more information on this process, see [validation process](./head-validation.md). Roblox expects the following 3 distinct landmarks in your cages: @@ -68,7 +67,9 @@ Roblox expects the following 3 distinct landmarks in your cages: -Even for non-humanoid faces that don't include visual eyes or mouths, it's important to ensure that these landmarks still exist and can be projected over your base mesh. +The mouth landmark vertices are on the **second loop** of vertices from the mouth opening. This precision may help prevent issues with [landmark validation](./head-validation.md#landmark-projection). + +
## FACS animation @@ -95,7 +96,7 @@ Roblox supports facial animation on character heads and can support more than 50 While the 17 poses are a minimum requirement, it's recommended to include as many facial poses as possible in your asset to improve expressiveness and facial animation fidelity for facial animation and avatar chat. -To pass validation, the character head must successfully perform the following 5 facial actions. If the head can't deform at the points of the [cage landmarks](#head-cage) for these facial actions, validation fails for the asset. +To [pass validation](./head-validation.md), the character head must successfully perform the following 5 facial actions. If the head can't deform at the points of the [cage landmarks](#head-cage) for these facial actions, validation fails for the asset. diff --git a/.cursor/rules/roblox/en-us/art/characters/head-validation.md b/.cursor/rules/roblox/en-us/art/characters/head-validation.md new file mode 100644 index 00000000..f30521b0 --- /dev/null +++ b/.cursor/rules/roblox/en-us/art/characters/head-validation.md @@ -0,0 +1,218 @@ +--- +title: Head validation +description: In-depth details on how Roblox validates head assets +--- + + +This content is for creators who intend to create character heads designated for the Marketplace, or any character heads that support assets from the Marketplace. + + +Roblox runs a rigorous validation to ensure the asset being uploaded to the Marketplace is compatible with all other assets on the Marketplace. For heads, validation primarily ensures that the head asset includes: + +- A correctly **configured cage** — to wear clothing and accessories. +- Correctly configured **facial animation poses** — to perform basic universal expressions, such as blinking and smiling. + +The primary validation check for heads [uses the cage to detect facial animation](#facial-animation-detection). See below for a reference of how validation processes, as well as [common issues](#common-issues). + + +Validation also checks for other issues, such as poor caging or missing required FACS poses. For more information, see [common issues](#common-issues). + + + +Auto-setup recommendation +
+[Avatar auto-setup](../../avatar-setup/auto-setup.md) is an automated tool that automatically generates components for your avatar character, **including the head cage and facial animation** required for Marketplace character models. You can save time by submitting character models without avatar components into the auto-setup tool and modifying the output. + +You can test and refine your auto-setup output by using the Avatar setup tool previews. You can even download your output as a `.gltf` and adjust the FACS or cage data in your DCC tools. + +You can alternatively manually modify your own cages and FACS animations within your DCC tools, which may require more time or additional iteration in your workflow, such as weight-painting adjustments, to ensure it meets Marketplace policies. + +To submit issues or feedback regarding the avatar auto setup tool, submit a [bug report](https://devforum.roblox.com/c/bug-reports/10). +
+ +## Facial animation detection + +One of the primary dynamic head validation checks verifies if your head asset has **visually discernable** animations. To achieve this, the validation tool uses the head cage to ["project" landmarks](#landmark-projection) onto your base mesh. + +After these landmarks created, validation [tests various face animation poses](#facial-animation-detection) to ensure that these landmarks move and deform appropriately. Validation succeeds when it detects appropriate movement of the landmarks for eyes closed, mouth open, and basic happy/sad expressions. + +Failure to either assign landmarks onto the base mesh, or failure to deform landmarks appropriately can occur for several reasons. For more information, see [common issues](#common-issues). + +### Landmark projection + +Validation uses the head cage to project landmarks onto the head mesh. This helps Roblox establish where the eyes and mouth are and helps guide the facial animation test. + + + +
+ + +
Cage mesh: Specific vertices of the cage mark eyes and mouth.
+
+ +
+ + +
Roblox validation projects these points onto the head mesh.
+
+
+ +
+ + +
Head mesh: All landmarks projected from cage mesh to head mesh.
+
+
+ + +Once validation verifies that projection is successful and all landmarks established onto the head mesh, it can move onto testing facial animations. + + +### Test face animations + +Now that the validation system knows where to check for the eyes and mouth, the validation checks for facial animations to ensure that the following basic actions are possible: + +- Left and right eyes can close +- Mouth can open +- Basic happy and sad expressions + - For a full list of basic action units and poses, see [FACS animations](./head-specifications.md#facs-animation). + +The validation looks for the **relative change in the landmarks**. For example, when testing for right eye closing (FACS pose: `RightEyeClosed`), validation checks if the landmarks move from their original neutral state accordingly. + + + +
+ + +
Face mesh with all projected landmarks applied from cage.
+
+ +
+ + +
+Validation verifies that the right eye can close based off of displacement of landmarks. +
+
+
+ +## Common issues + +Validation checks for several aspects of your head asset. If you are receiving an error related to dynamic head animation, use the following table for potential culprits: + +
+ + + + + + + + + + + + + + + + + +
IssuePotential fixes
The validation tool is **unable to successfully apply landmarks**.

See [Unable to project landmarks](#unable-to-project-landmarks).
- Verify that the **cage landmark vertices are positioned directly over the corresponding areas of the face**.

- Verify that the **cage is not intersecting with the head mesh**. Landmark projection expects the cage to be over the head mesh.

- **Check for any gaps, holes, or difficult surfaces** of the face where landmarks can fail to project.
The validation tool is able to apply landmarks, but **can not detect animation**.

See [Animations not displacing landmarks](#animations-not-displacing-landmarks).
- Verify that **landmarks are on the areas of the eyes and mouth that move during animation**.

- Verify that the **cage is not intersecting with the head mesh**. Landmark projection expects the cage to be over the head mesh.

- **If using separate meshes for eyeballs and mouthbags**, ensure that your landmarks are applied to the head mesh, not the eyeballs or mouthbag. This can be achieved by slightly widening the area where your cages project landmarks.
The validation tool doesn't detect [FACS animations](#animation-data-missing).- Your head doesn't include FACS animation. Verify that your head includes FACS poses and mapping.
+ +### Unable to project landmarks + +If validation is unable to apply the projection correctly onto the surface of the head, the validation fails. This often occurs if your **cage extends beyond your head mesh**, or if your head mesh has a **hole or gap** that prevents the application of the landmark. See the following examples: + + + +
+ + +
Cage **extends too far beyond the mesh** and the validation is unable to apply 3 landmarks to the base mesh.
+
+ +
+ + +
+Base mesh has a **hollow gap** in the design, preventing validation from applying 3 landmarks to denote the eye area. +
+
+
+ + +In both cases, adjusting the cage to allow the proper projection of landmarks to the base mesh would resolve this issue. + + +### Animations not displacing landmarks + +In the case where landmarks are correctly applied to the base mesh and the base mesh includes FACS data, it's possible that the facial animations do not displace the landmarks enough to pass validation. See the following example: + + +
+ +
Landmarks successfully established on base mesh, but are not near the expected regions.
+
+ +
+ +
When testing animations, validation doesn't detect the expected change to the landmark regions.
+
+
+ + +In the example case, adjusting the cage to allow the proper projection of landmarks at the appropriate areas would resolve this issue. + + +There may also be cases where the landmarks are correct, but the animation itself does not alter the projected landscapes enough to pass validation. In these cases, fixing the animation and/or optimizing the cage could help the validation properly identify the facial animation. + +### Animation data missing + +Heads require [17 specific FACS poses](./head-specifications.md#facs-animation) that are used to test the 5 basic actions. Regardless of landmarks or other FACS animations, validation immediately fails if the minimum 17 poses were not detected. + +For information on how to pose and map dynamic heads, see [Creating basic heads](../characters/facial-animation/create-basic-heads.md). + +## Working with non-humanoids + +Some character models, typically non-humanoids, have unnatural or missing eyes and mouths. The most common case of this is the classic blocky features. + +In this case, the cage still applies the expected landscapes to the head surface, and Roblox validates if facial animations correctly displace the facial animations. + + +
+ +
The cage for a blocky character applies landmarks to the surface of the head.
+
+ +
+ +
Ensure that the landmarks are applied in areas where animation can effectively move the landmarks.
+
+ +
+ +
Validation checks the displacement of the landmarks to verify facial animation.

Make sure that your [FACS animations](./head-specifications.md#facs-animation) properly affect the region where landmarks are applied.
+
+ +
+ +In cases where eyes and mouths might be missing, the validation still projects landmarks and expects facial animation in those areas. + + +
+ +
Although this character doesn't have eyes or mouth, the cage still attempts to project landmarks for those features.
+
+ +
+ +
In this example, the cage landmarks apply to the surface of this eye-less character head.
+
+ +
+ +
Validation checks the displacement of the landmarks to verify facial animation.

Make sure that your [FACS animations](./head-specifications.md#facs-animation) properly affect the regions where the landmarks are applied.
+
+ +
diff --git a/.cursor/rules/roblox/en-us/art/characters/index.md b/.cursor/rules/roblox/en-us/art/characters/index.md index ae2e483d..943ea180 100644 --- a/.cursor/rules/roblox/en-us/art/characters/index.md +++ b/.cursor/rules/roblox/en-us/art/characters/index.md @@ -3,7 +3,7 @@ title: Avatar characters description: All Roblox users are represented by an avatar character which can be customized with body parts, accessories, and clothes from the Marketplace or within experiences. --- - +

diff --git a/.cursor/rules/roblox/en-us/art/index.md b/.cursor/rules/roblox/en-us/art/index.md index e0a0147c..32b29b14 100644 --- a/.cursor/rules/roblox/en-us/art/index.md +++ b/.cursor/rules/roblox/en-us/art/index.md @@ -48,7 +48,7 @@ Whether you're just getting started with Roblox or need a quick refresher, use t
- +
Create avatar items Create accessories, clothing, and bodies that you can sell on the Marketplace. @@ -74,7 +74,7 @@ that teaches you the skills you need to create and monetize your experiences.
- +
Environmental art Environmental art teaches you how to recreate a high-quality environment for a first-person laser tag experience. @@ -93,7 +93,7 @@ style={{position: "relative", paddingBottom: "56.25%", height: 0}}>
- +
Avatar item tutorials Check out our tutorials on creating your own Avatar items ready for the Marketplace. @@ -166,7 +166,7 @@ style={{marginRight:8, alignSelf: 'flex-start'}}>Learn more
- +
Custom skyboxes 101 diff --git a/.cursor/rules/roblox/en-us/art/modeling/3d-importer.md b/.cursor/rules/roblox/en-us/art/modeling/3d-importer.md index 0747c59a..0677abfa 100644 --- a/.cursor/rules/roblox/en-us/art/modeling/3d-importer.md +++ b/.cursor/rules/roblox/en-us/art/modeling/3d-importer.md @@ -379,7 +379,7 @@ You can use the **⋯** menu next to the Presets dropdown for additional opt ## Warnings and errors - +
If Studio detects any issues with your model, a small indicator displays in the hierarchy panel or the settings panel. diff --git a/.cursor/rules/roblox/en-us/art/modeling/reimport.md b/.cursor/rules/roblox/en-us/art/modeling/reimport.md index ae9b8500..0d843b17 100644 --- a/.cursor/rules/roblox/en-us/art/modeling/reimport.md +++ b/.cursor/rules/roblox/en-us/art/modeling/reimport.md @@ -11,7 +11,7 @@ For latest information on updates and limitations, see the [DevForum Announcemen **Reimport** allows you to update existing custom models and their textures from an external 3D file. Unlike regular [import](./3d-importer.md#import-files), which creates brand new instances, the reimport function updates existing objects non-destructively to help support the iterative nature of 3D development. -
+
Along with asset updates, reimport remembers the file and settings used to import the original asset. This means you can easily update an imported asset with a single click or hotkey without going through all the initial import settings. This memory persists across Studio sessions. diff --git a/.cursor/rules/roblox/en-us/assets.md b/.cursor/rules/roblox/en-us/assets.md index f13943c8..55cb844c 100644 --- a/.cursor/rules/roblox/en-us/assets.md +++ b/.cursor/rules/roblox/en-us/assets.md @@ -124,7 +124,7 @@ export const sections = [ frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" - allowfullscreen + allowFullScreen > )} diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Blocky-All.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Blocky-All.png new file mode 100644 index 00000000..34826b89 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Blocky-All.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb022feeee06dcaabfd345fa0af209f8870928c0814b598509350645da0bea41 +size 464798 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Blocky-Cage.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Blocky-Cage.png new file mode 100644 index 00000000..8ced7d7b --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Blocky-Cage.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8722390fd278acaf06425785e5fa05d569bcc76242569c27b74de541aa0529fa +size 375811 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Blocky-Head.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Blocky-Head.png new file mode 100644 index 00000000..d66c44e3 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Blocky-Head.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:87e5b874503766793ece7e6bfda827deb331a66e0bcca6a06a796758fbcc133e +size 315364 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Cage-Face-Offset.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Cage-Face-Offset.png new file mode 100644 index 00000000..796dd2a3 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Cage-Face-Offset.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef74b51fecdd458218d8f6ec012e3bc1bdab6cd71df454ba1a62781cf0f1ec39 +size 162093 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Cage-Landmarks.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Cage-Landmarks.png new file mode 100644 index 00000000..a7317a99 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Cage-Landmarks.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a63f680331a7b20092f8f9ae7b5ce76d09e5d39b5c1e6bd6466bee5cf2b9532 +size 156644 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Cage-Reference-A.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Cage-Reference-A.png new file mode 100644 index 00000000..d5939c5b --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Cage-Reference-A.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00a0091d934c1e53c9b836ec64ceafa08c47fb22d6091499b3ba66926955b430 +size 642539 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Cage-Reference-B.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Cage-Reference-B.png new file mode 100644 index 00000000..a09c2810 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Cage-Reference-B.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:666a7ff0fd1c8d97ca0dfd7acbee4c814118064c9944ace14671891aba76204a +size 259622 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Cage-With-Landmarks.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Cage-With-Landmarks.png new file mode 100644 index 00000000..84ead376 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Cage-With-Landmarks.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c34236bc359db35c9d13a686a2fbcd8d013ba20af1ce22a774b482f8fe756d1c +size 162596 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Eye-Closed-Success.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Eye-Closed-Success.png new file mode 100644 index 00000000..54e7917c --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Eye-Closed-Success.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d9e11f29a4e5ffadc64ea2ba623217f364b1b20f9f5034094e8b36fb1d9d5333 +size 193902 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Face-Default.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Face-Default.png new file mode 100644 index 00000000..6c333b87 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Face-Default.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:97fffa11b42454c531c4ad8913b9e6d36bf804b3059395596822be1edcd098c6 +size 278004 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Face-Landmarks-Poor.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Face-Landmarks-Poor.png new file mode 100644 index 00000000..911ca16c --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Face-Landmarks-Poor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:17fe359fcd30a86aedd67e1043437b2692336a50d1833896af6852c16934db24 +size 280432 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Face-Landmarks.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Face-Landmarks.png new file mode 100644 index 00000000..c0cd79b9 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Face-Landmarks.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f50c7e2968792f3012bde4b00b882080c4201f6d0ff50808a26509ae1ea412c +size 280497 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Horn-All.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Horn-All.png new file mode 100644 index 00000000..4bbf912c --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Horn-All.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7856e7a72cc749a684ad8bdb76a9e4780b9aedb349f960341cf57ee05a1f7979 +size 140092 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Horn-Cage.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Horn-Cage.png new file mode 100644 index 00000000..d2332142 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Horn-Cage.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e49f90344a036c4f70b7e2b72b328d6e2e030654f5e66a15e096d481b21a8266 +size 110549 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Horn-Head.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Horn-Head.png new file mode 100644 index 00000000..2d07b2ec --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Horn-Head.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ecb5d242163ea58767bd08a3d37bc747e1435ab01f5c8860515344561806a3a2 +size 63702 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Landmarks-Fail-A.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Landmarks-Fail-A.png new file mode 100644 index 00000000..a94b4fe4 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Landmarks-Fail-A.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:32b66a226ab23b8fd68b995039f63474042deda3c97ea86c7b5f3908cc12cb77 +size 282867 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Landmarks-Fail-B.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Landmarks-Fail-B.png new file mode 100644 index 00000000..52c6bc73 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Landmarks-Fail-B.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:64aa7237f46563b60f7f613d3698a95c24fe4a11928913a51551cbc1491834e8 +size 201370 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Missing-Landmarks-A.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Missing-Landmarks-A.png new file mode 100644 index 00000000..48b5af5e --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Missing-Landmarks-A.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:43e87f3e48cdc1f1fdbad15c58b23aff2edb4ed7c3980812658d6218da1972a1 +size 219156 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Missing-Landmarks-B.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Missing-Landmarks-B.png new file mode 100644 index 00000000..4e1e0043 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Missing-Landmarks-B.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fee21615299541dabce94ecd36395a525d78bd21abf1c264e3633c1e53a5d5aa +size 241801 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Mouth-Vertices-Warning.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Mouth-Vertices-Warning.png new file mode 100644 index 00000000..38abd5b3 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Mouth-Vertices-Warning.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:65dd75a3afe11df7eb126736bc4303d12c09c15aea05b28cb1d979a1ca884621 +size 102567 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/Projection-Side.png b/.cursor/rules/roblox/en-us/assets/art/avatar/Projection-Side.png new file mode 100644 index 00000000..449be945 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/Projection-Side.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:017b78c42becdf1e094e4f2b264b6c9091e9c68602944d40b6b287a1ccb7c7da +size 173273 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/20_406000958.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/20_406000958.png new file mode 100644 index 00000000..31ef1ed6 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/20_406000958.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e15538acb4fe2bdab9818152b00e5489213d4c8da549c65c7a0e7effa54aca56 +size 36286 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/3.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/3.png deleted file mode 100644 index 1d346504..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/3.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7a7e13d08352eea7bc4dd3a8d91be4eab5198a040dfeb28ad7b8f5a36117aca2 -size 80854 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/3_15432080.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/3_15432080.png new file mode 100644 index 00000000..976ef363 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/3_15432080.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79b980f6daa0a82408c9a5e840215e342bd4d80ac6c484d89e802514a117e100 +size 50093 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/8bit_Heart_Face_2568799765.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/8bit_Heart_Face_2568799765.png new file mode 100644 index 00000000..3ca2a5c6 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/8bit_Heart_Face_2568799765.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dc255008da4cdb8fbda00a05a6492c361b668875c6ef183724c0a40d8f0070be +size 54306 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Adorable_Puppy_11389372.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Adorable_Puppy_11389372.png new file mode 100644 index 00000000..c30b6f62 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Adorable_Puppy_11389372.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c96e778ef21e786b4246af38d51d7235c08f858be1c09ae7a372491ebc769ad8 +size 54567 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Alien_31317701.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Alien_31317701.png new file mode 100644 index 00000000..4d5a120b --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Alien_31317701.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a9bb83af002a298c856f9c4b48ed211bb96c7bdbc834402a9c5cf8ea459b16b8 +size 47316 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Alien_Ambassador_11913700.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Alien_Ambassador_11913700.png new file mode 100644 index 00000000..bf1d34bb --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Alien_Ambassador_11913700.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:13111576730b9ea431a7eb0b27b6a8b51ccf999701151e8a5698d1f2f16d959e +size 49924 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Alright_7131541.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Alright_7131541.png new file mode 100644 index 00000000..73d75171 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Alright_7131541.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b32d2037813551bf199ed0711fbc2d0305e3fa296a0544e1a265bcc70f16fd27 +size 57930 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Amelia_Face_293302465.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Amelia_Face_293302465.png new file mode 100644 index 00000000..63c33750 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Amelia_Face_293302465.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:83fe874cf88414282e63135000b7499e5dac8fdf6cb5badaf2ef9a51cdb23e39 +size 62894 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/And_Then_Well_Take_Over_The_World_12732366.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/And_Then_Well_Take_Over_The_World_12732366.png new file mode 100644 index 00000000..46fea0af --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/And_Then_Well_Take_Over_The_World_12732366.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ae4db14ba11dcedec5992825f78c67f40fcedff2b39fb9638c42fcc1875285c +size 51437 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Angelic.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Angelic.png deleted file mode 100644 index 92db7095..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Angelic.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bfd51e5cd9c278106546ab33089548dee20862cdaf2a65d4e0db3ad553b1a95e -size 86199 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Angry_Zombie_173789114.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Angry_Zombie_173789114.png new file mode 100644 index 00000000..82d60d64 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Angry_Zombie_173789114.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:396ebf835e937b8f9ecc8e42f297e1cca5404dcdb9965a4eea7b9d12745dcecd +size 63164 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Anguished_8560975.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Anguished_8560975.png new file mode 100644 index 00000000..80511d23 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Anguished_8560975.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b449d96482d364509e3e5a1ca615dab42e7c8e88c6b01a888619aa9044732eda +size 56226 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Anime_Surprise_416846300.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Anime_Surprise_416846300.png new file mode 100644 index 00000000..bb783ad7 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Anime_Surprise_416846300.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:84ca49a5b7610e939f2289ca5fa7317ad3b58b25b7a1fe4e77d3335c26b5aae3 +size 65443 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Award_Winning_Smile_6531983163.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Award_Winning_Smile_6531983163.png new file mode 100644 index 00000000..3424c349 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Award_Winning_Smile_6531983163.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e98c0c1f9dcdb71e9f3ee82e2fe018c0122e8659f1df8260ea30d13d69548a0 +size 79636 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Awesome_Face_30394850.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Awesome_Face_30394850.png new file mode 100644 index 00000000..08889cbb --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Awesome_Face_30394850.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14ad7dce8575adb963d4962b49bc22048e9657e796eaa424cec49e3241661724 +size 60986 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Awkward_23932048.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Awkward_23932048.png new file mode 100644 index 00000000..01601340 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Awkward_23932048.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b1600c402e1df6716a502a3a095aa3c9ed4faa5423c6f02b77eae1c32ca817f1 +size 56324 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Awkward_Eyeroll_150182378.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Awkward_Eyeroll_150182378.png new file mode 100644 index 00000000..476c2fde --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Awkward_Eyeroll_150182378.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8216b81a372a1a9e5f80ec1a93bd5ecd5de3dcc15f9ffdc350d8400d7588774b +size 51328 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Awkward_Grin_150182501.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Awkward_Grin_150182501.png new file mode 100644 index 00000000..c2a2bd08 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Awkward_Grin_150182501.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:81bca79374de004430e19fc1c2d51f626d9f235754c24dd77b34a2d1f220eddd +size 60315 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bacon_Face.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bacon_Face.png deleted file mode 100644 index ce0cd01f..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bacon_Face.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cdf9d8719a81005189b7ffa7b4b60b8a7849a453f9c52c5de0e155086382619d -size 98942 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bad_Dog_10678423.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bad_Dog_10678423.png new file mode 100644 index 00000000..90797826 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bad_Dog_10678423.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18ffea32e8ae232e0d2237f1d53a96f1a975172e4cffc3cf5a1896baf6f8ceb2 +size 57386 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bandage.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bandage.png deleted file mode 100644 index d723784b..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bandage.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c2dd086a35d84230337e29901cd78d9f2d1be9063bde44a862bf27a65c53cf33 -size 96012 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Beaming_With_Pride_3267567501.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Beaming_With_Pride_3267567501.png new file mode 100644 index 00000000..a15358b8 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Beaming_With_Pride_3267567501.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:91591f87d0e7f27d8f97364db23ece7cae762437cdf97bff78c986a4fef54cfd +size 105609 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Beast_Mode.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Beast_Mode.png deleted file mode 100644 index 8c9e4c81..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Beast_Mode.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:26a6b814dcb52bca3147c8b52f0e475c6de67d9d19fd18e3e7e7c9ae2c681129 -size 106215 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Beast_Mode_128992838.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Beast_Mode_128992838.png new file mode 100644 index 00000000..bcec1753 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Beast_Mode_128992838.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:83484ed9f4a37cf610ee3d80b579a9ea019b03cdca39219d0de380391bc3e601 +size 71163 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Big_Grin_Tai_Verdes_7987180607.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Big_Grin_Tai_Verdes_7987180607.png new file mode 100644 index 00000000..1896e41f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Big_Grin_Tai_Verdes_7987180607.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:158636ed3788f981a214235c8b80c789260dafb329b489dd43b8d6959080362f +size 96799 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Big_Sad_Eyes_391496223.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Big_Sad_Eyes_391496223.png new file mode 100644 index 00000000..c58ce3ed --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Big_Sad_Eyes_391496223.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:449b9d909d85dd96d396809844e5dbd145c33f08022aec1077c4335f927a7473 +size 49477 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Biteymcface_743690770.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Biteymcface_743690770.png new file mode 100644 index 00000000..e6c1a2c9 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Biteymcface_743690770.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:20286a44f83eba192eb45dcd3cd3a1fc2cd33e80382ac4b1c4fe310891974e89 +size 57840 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blerg_12777646.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blerg_12777646.png new file mode 100644 index 00000000..eb137ae6 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blerg_12777646.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c533115109ed33894c336cf2bf94d74e3b84154cc69242797c4a4e71e2375e99 +size 48641 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bling.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bling.png deleted file mode 100644 index 1bc5bb9b..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bling.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2d11742d39eee7b628bd3edc139edb6ffce8041076b564e04d1963e2d410b6a1 -size 100710 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blinky_7506135.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blinky_7506135.png new file mode 100644 index 00000000..5e180ff3 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blinky_7506135.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d84b02aca8cfa1825ff3d76d33af7d292774e30ee7d35605ec3f5aff4f45721 +size 52745 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blizzard_Beast_Mode_209995252.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blizzard_Beast_Mode_209995252.png new file mode 100644 index 00000000..a90ec41f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blizzard_Beast_Mode_209995252.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c98f948e9f470166a25fd213066b1e09854618c50c7ba00b4624074a4ec0c677 +size 70749 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Amazeface_835095003.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Amazeface_835095003.png new file mode 100644 index 00000000..ed9d1301 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Amazeface_835095003.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eaf1243c0831678a4c2e3c31cae0d2af6be1b9d141cd025639c9fff96f793cfd +size 62016 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Bubble_Trouble_330296924.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Bubble_Trouble_330296924.png new file mode 100644 index 00000000..599e3b44 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Bubble_Trouble_330296924.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9f2b26ba9d956f2f6ae8b876388cee960b4258112a4edd1eef01864b15bb6475 +size 61960 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Eyeroll.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Eyeroll.png deleted file mode 100644 index 56930215..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Eyeroll.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7b025f6abb8a7383601e823dd0da26576eb0c3184e10186fe9ccdb2a87258208 -size 82661 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Galaxy_Gaze.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Galaxy_Gaze.png deleted file mode 100644 index cc11758d..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Galaxy_Gaze.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9140f3ba42db44eac39396cbb93e6529567603092fea2073bd29cd8d4bc59784 -size 91751 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Goof_1191162013.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Goof_1191162013.png new file mode 100644 index 00000000..f6e7333c --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Goof_1191162013.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00c95002b9b6599e00c664def1819a2debff2fac6b0e60711e3793262ee74525 +size 68688 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Rock_Star_Smile.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Rock_Star_Smile.png deleted file mode 100644 index cc36496c..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Rock_Star_Smile.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8aa6b46583667fac1232f693f8bdf574594a2e1ffea0c6e08799df9d4d0c9c1e -size 95403 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Rock_Star_Smile_1428409936.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Rock_Star_Smile_1428409936.png new file mode 100644 index 00000000..df12d1ae --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Rock_Star_Smile_1428409936.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b962e80e88b306f31794f96d84a790021806822ac782114ec13f7852cb2830eb +size 61796 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Starface_119812715.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Starface_119812715.png new file mode 100644 index 00000000..d7e60bc5 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Starface_119812715.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3447987b5d3c705516409d6fc8261754dbb741c1e7c8ea6ec8792a4ee8d663aa +size 67348 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Starry_Sight_2222775067.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Starry_Sight_2222775067.png new file mode 100644 index 00000000..d4dc3bda --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Starry_Sight_2222775067.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e9ced971531f5b4a067c12cd40ab0fba977ebb95b96acc65bf1fb185194df4f0 +size 64626 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Ultimate_Dragon_Face_1772529256.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Ultimate_Dragon_Face_1772529256.png new file mode 100644 index 00000000..52e850d6 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Blue_Ultimate_Dragon_Face_1772529256.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:49e3a4379d757d47044a12897c316420940e48e3373d89ab2aaa22bcb49bcd6c +size 78082 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bluffing_147144673.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bluffing_147144673.png new file mode 100644 index 00000000..854f83b5 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bluffing_147144673.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff8e5cd91a6993cfceed2598fb93f048a9dadce27c90cc281166011f61b9a983 +size 49417 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bombo_Face_121947053.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bombo_Face_121947053.png new file mode 100644 index 00000000..4cf5c1ca --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bombo_Face_121947053.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:66dbe6b823cac5953c9236b338dcd84c44763a0b51624e1115586551ce8a846d +size 79493 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bored_66330106.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bored_66330106.png new file mode 100644 index 00000000..8d6f74e1 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bored_66330106.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24c060fc935e0c8cf471895b8e6965bad7b33e2672ed66283bb5465ad87b7b6d +size 45417 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Braces_30394484.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Braces_30394484.png new file mode 100644 index 00000000..7c02174b --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Braces_30394484.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f489c91a9b333a6bb07c28873bd1ed763a4a231dba87f31b537e26ef6e7d005 +size 55841 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bubble_Trouble_19264845.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bubble_Trouble_19264845.png new file mode 100644 index 00000000..e42f002e --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Bubble_Trouble_19264845.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:09a12ab9b4b039a51987e2856d237b4fc93c4d52abb3435acc67cabb4b8e2b67 +size 61013 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Butterfly_Wink_Lil_Nas_XLNX_7657646351.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Butterfly_Wink_Lil_Nas_XLNX_7657646351.png new file mode 100644 index 00000000..4fea835e --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Butterfly_Wink_Lil_Nas_XLNX_7657646351.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0fb0459a365daaec6ddadd2566076d614af03b57e199e3825a03d7baa29ba03b +size 114810 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Camoface.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Camoface.png deleted file mode 100644 index f323693f..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Camoface.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7dd914b5edd67fc5d1d84a5a6c4d7d483811e72412ed8ca6853a6af6f47ecc27 -size 152444 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Caret_Underscore_Caret_15366173.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Caret_Underscore_Caret_15366173.png new file mode 100644 index 00000000..7d905b64 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Caret_Underscore_Caret_15366173.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:202d37739a673cbc8708681b7b7361d00257f44af649a6135873cd5f6ce474ff +size 44499 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cat_Eye_-_Zara_Larsson.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cat_Eye_-_Zara_Larsson.png deleted file mode 100644 index 01ee4671..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cat_Eye_-_Zara_Larsson.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3d33f40ed95f554ab4f12f7e293f004383476ab1bc4a71c02919c23ab933bd55 -size 155413 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cat_Eye_Zara_Larsson_7893455671.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cat_Eye_Zara_Larsson_7893455671.png new file mode 100644 index 00000000..1408a44b --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cat_Eye_Zara_Larsson_7893455671.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf97600e0afca9e17fdc857f6f5008a13175eb39b480c407d787cef40e88aabb +size 117430 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Check_It_7074786.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Check_It_7074786.png new file mode 100644 index 00000000..06b636cc --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Check_It_7074786.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c34951b69733f065d69aec46c45bd6f3c885203016b461a163314958d3a8ee22 +size 49600 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cheerful_Grin_33321848.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cheerful_Grin_33321848.png new file mode 100644 index 00000000..fbf03a74 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cheerful_Grin_33321848.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:53a7e3291304c8e9a14b9cde53ea8d01cab32b214e71e4127bd1fa7474bba318 +size 51928 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cheerful_Hello_362051644.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cheerful_Hello_362051644.png new file mode 100644 index 00000000..771b7ae8 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cheerful_Hello_362051644.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:653fce08261b0d5485bfb579f1a054022773b8f5d542d04e0c05ea16ce3b8b48 +size 53703 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Chill_7074764.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Chill_7074764.png new file mode 100644 index 00000000..8f9a5cef --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Chill_7074764.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5c1dc011d63d0f1bbb21da45173383c22b5549181be804b3cfbd6c788b017284 +size 44401 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Chill_Mccool_376813144.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Chill_Mccool_376813144.png new file mode 100644 index 00000000..d74644d4 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Chill_Mccool_376813144.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a5b1ad62c3f1e364998c0438b4921ae05190bb2355fb7334ef622ddf34e7b99 +size 52985 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Chubs_7076110.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Chubs_7076110.png new file mode 100644 index 00000000..50151104 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Chubs_7076110.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:248c24e7f15c814940bbbd9450f21e61105cb74d833a7c25a1f419195e9c36b3 +size 45400 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/City_Life_Man_Face_2490662812.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/City_Life_Man_Face_2490662812.png new file mode 100644 index 00000000..5b349188 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/City_Life_Man_Face_2490662812.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd5d100dd7a342b774794457a90645fd719f86c949f7c44886cf5d57f5d96bbc +size 77606 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/City_Life_Woman_Face_2492678267.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/City_Life_Woman_Face_2492678267.png new file mode 100644 index 00000000..56b4bbbb --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/City_Life_Woman_Face_2492678267.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d2bfaa67d5949850b5fb4f67ea67c77f472a3d9b7836a0f9d59e007d4be8065e +size 89131 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Claires_Face_301827089.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Claires_Face_301827089.png new file mode 100644 index 00000000..7ee4b2a3 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Claires_Face_301827089.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c9bf6c1135902cd700333e78a5ccc0afee1716e09456f5cf6f6e4d314900ab40 +size 56429 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-1.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-1.png deleted file mode 100644 index c2d31c38..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:91897e37c2392f14af6b450ef5da027df97dcf64ca95aefd91175883528ca517 -size 49875 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-10.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-10.png deleted file mode 100644 index 3a0d116a..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-10.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5af6f39f6fcaa559eec3ee73b274f4ffa8bf4a53fda2753bc387c354d4ba17fb -size 121157 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-11.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-11.png deleted file mode 100644 index 4e5741db..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-11.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:547e02f01312a70f41a362439774d9bdc4c60d77ebcf2fc47c1efc1d645da666 -size 60527 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-12.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-12.png deleted file mode 100644 index 154b9dfd..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-12.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b150693a04fe36b4ad8ee734f27f4c96328fc194ef475a12a09e7648c11a58b2 -size 81487 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-13.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-13.png deleted file mode 100644 index 69c8c53f..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-13.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:94aae09c47bfb18ce65e17ef9efe71686704bc85b1a51d55d27e09513bcbacd5 -size 65736 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-14.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-14.png deleted file mode 100644 index 7f076162..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-14.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:96ce7efcfb48af8a87b6096a16939f65b55c76b8039c63b5751133d01b377f5e -size 108084 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-15.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-15.png deleted file mode 100644 index 0e59aa8d..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-15.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a40f1664d4b779db645f9f2dc91f92891142eb7e2df8c23eb8168661c4a21e47 -size 57174 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-16.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-16.png deleted file mode 100644 index 892dca9d..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-16.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d8e84b56b5432efea5fe503837ddb06c2137ec6f4469d9326b102e1f66431045 -size 68456 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-17.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-17.png deleted file mode 100644 index 3b72e0f5..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-17.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:79f7ee2fba85bc5ca8d888fbfd85d28fbf2ffc7ebeb59b167cd66197b6541fb0 -size 65632 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-18.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-18.png deleted file mode 100644 index 468c79e1..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-18.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a64b8490ce0029ef923f7f644935d52ed7a71a27060df642e1df3585bfdec359 -size 59565 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-19.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-19.png deleted file mode 100644 index c49e9091..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-19.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dd1ce90d6cd00a7b573cc41622cc93d2fa7017efbf1e6997845cd20f4305b31c -size 78043 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-2.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-2.png deleted file mode 100644 index 9d714bbc..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a7385f962b6e2a4b5e6a6a6c58ad8b96992b226e2be33f06ced3093c3479094f -size 63373 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-20.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-20.png deleted file mode 100644 index a7ad02fc..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-20.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:93e5f9ff7c93337ee569e98dc3823bacc5c4c201d30c837345c50c923bb64531 -size 72603 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-21.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-21.png deleted file mode 100644 index 615d9451..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-21.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9081a10549dfabc1107ce643301cd0796041fd91fa1836abdf34e95299049449 -size 69014 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-22.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-22.png deleted file mode 100644 index a93de136..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-22.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d98afc3104aecf37c30b5be35a965144ab7e25239874a0a59af1b6df1f606747 -size 71468 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-23.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-23.png deleted file mode 100644 index 0edd938a..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-23.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5472dbe825dafb31adcc24c278b604d0b71fcfd7d9d93d965e956f7077dfde97 -size 89870 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-24.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-24.png deleted file mode 100644 index 88d5eb23..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-24.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:190ad1170df9867d55026dcd570a68925259fd6718c1018aabc9049221bf0e70 -size 63554 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-25.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-25.png deleted file mode 100644 index de868d9c..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-25.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a61c11ca1d4e07978edc2aefb54736ab5684748c73c2224f839881a4dc5ba82c -size 74869 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-26.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-26.png deleted file mode 100644 index 0cd7fc35..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-26.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f8901d41846a8dee6ea03e54ee5c2349c2f42708d52178fcdda64ee4194e26fd -size 69914 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-27.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-27.png deleted file mode 100644 index 81e3db1e..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-27.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d5316d957a13d790eb5c7b4909bf60245177952a71cf84391c31a2fd06e84a02 -size 66593 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-28.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-28.png deleted file mode 100644 index 225edda3..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-28.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:894296bd58b096f1e641c42016927772834600b32276a8fec42814eada6bf475 -size 75868 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-29.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-29.png deleted file mode 100644 index 3afa308e..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-29.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bd55bd221be1870d18bbd9bc8967dcc8edde6254c9ec6930cc55c9cec5b08657 -size 90798 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-3.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-3.png deleted file mode 100644 index f1f87f2a..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-3.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:58274e97672354a81702e2a15f88625f5651c363a3c7afeef5868e8bbb12e55a -size 81489 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-30.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-30.png deleted file mode 100644 index b2c9876d..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-30.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:930b8dbdb80714b301acce545fcf10810d3ee15bca9c47d8a8e2d4e0d70706fa -size 59921 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-31.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-31.png deleted file mode 100644 index 9122f6cb..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-31.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:49f2e3d8720fd6a732e630c4e07abbfcc43a0c2e72baf2f79e5a423a90df135e -size 74199 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-32.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-32.png deleted file mode 100644 index f81ef827..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-32.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0492fa8ff85e172b08b946516cf6925838a562212bd291bca867b484e7180675 -size 69808 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-33.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-33.png deleted file mode 100644 index 46ce5bd1..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-33.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d36512c8c9fe6349229b58e758460ebe0c874f3b226d108c743b101a2bc9a4d1 -size 83998 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-34.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-34.png deleted file mode 100644 index 2a459e82..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-34.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7a3856a209dc49adeb17c35ade5cf4a4d8dd46daa7e299a09bb6d704d3152280 -size 72426 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-35.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-35.png deleted file mode 100644 index 12c6fc53..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-35.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:902a7a1f8745547cdf09aeb7094dc011b28e4c6b2189a88323e3a67e87b5d4ad -size 52738 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-36.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-36.png deleted file mode 100644 index 25515220..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-36.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f4993198c6d3fa910276cd4d51fb5a51eaf59047cda14caf68fa4d0c7ac8a7b1 -size 51528 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-37.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-37.png deleted file mode 100644 index a86d6e22..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-37.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8c7acbb2df6885766908da92108b63ec63d581ccfc64a56c6f32accc13da133a -size 71681 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-38.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-38.png deleted file mode 100644 index 57a76ced..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-38.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bec4b732bd48dbde347fccb8c8efef057cde980a1f2596b65002fa45f5393c6f -size 61620 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-39.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-39.png deleted file mode 100644 index 15058895..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-39.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:23c30aadd41a0a7c4a64a0f3914ba99fcdec4a54a2e3b910918ff8b104d64a28 -size 62582 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-4.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-4.png deleted file mode 100644 index 16c33f04..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-4.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c73ece0974bb4e5767c4db7c7e790c77f3ba354c3e21a2ee630d720373845aec -size 76478 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-40.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-40.png deleted file mode 100644 index 748e55b7..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-40.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f5af297e31258463ba7ec83ad3fe04f53a43b79a2ed701fb2eb9c2971f764f9c -size 68725 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-41.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-41.png deleted file mode 100644 index 12de075e..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-41.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5157692702ec0fc1f1280916edea1ceda4f4df7cd920d476694409f73421e4af -size 64106 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-42.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-42.png deleted file mode 100644 index 3bee5da9..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-42.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:85a01ec7052bdd993f4c18dd4b1bb4c726a1607f5996a22bc45a78442fba1a3c -size 58126 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-43.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-43.png deleted file mode 100644 index 4ded776d..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-43.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f50d138c7ceda4d6a2b65100fc21bdc308f712d12258e249505596cb1e259ee7 -size 71165 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-44.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-44.png deleted file mode 100644 index cd912969..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-44.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6e948ee5f6fcef7b8c2c8c7728dcc60deb1d0df7c9a9d900af5ad124c58ac155 -size 54297 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-45.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-45.png deleted file mode 100644 index c04993a8..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-45.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:96ec1d9ece40790fe46bd81f974a9860ea3dcadc9ced6195676c40b2b073bfc9 -size 73438 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-46.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-46.png deleted file mode 100644 index 27c09f90..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-46.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1123513b2fccb30b2d8ea124d83cd5f4e695a9c14b46e3116e4ee10d6924d63f -size 72182 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-47.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-47.png deleted file mode 100644 index 56873af1..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-47.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7f684ba8c828b5dda246d6ccdf3611ea07f2960db9503fc55a0feb367a1b6cd0 -size 104893 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-48.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-48.png deleted file mode 100644 index 3eb7bea2..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-48.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:36cd5ebc8247fd8aad6a41bf0a8f9d99abb093c412c6166bd7e57c59672e0ce4 -size 66788 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-49.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-49.png deleted file mode 100644 index 0fb2817a..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-49.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8975ae4e00ff715dfc28a1cdd0651d72d6730eb904c9b25d22c860209b656112 -size 109054 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-5.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-5.png deleted file mode 100644 index 460632a4..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-5.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:42038b60b3770a14252fa75e355737686ea09b8ce884e1c0005d32dddd863942 -size 78461 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-50.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-50.png deleted file mode 100644 index 98e448bf..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-50.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a4ecb6c4befef506345b120e0263a34d83a16b5b725189549c440fbeb0c83056 -size 81360 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-6.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-6.png deleted file mode 100644 index 40458b09..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-6.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f60bfc7e6f7f0d0636f006983e6bddb241175d23100ed6d858d7a302569a0ffd -size 76320 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-7.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-7.png deleted file mode 100644 index 3e0e0203..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-7.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:66783a993794c804683a63055dbf6c89bb0d8e0a7d3fc0a8bc2ee4a53bf5974e -size 59097 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-8.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-8.png deleted file mode 100644 index fa25e477..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-8.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:af105ddd6390f34f944f4bbdf1cd836ce1e873339166960cd000e866d7aae502 -size 64582 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-9.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-9.png deleted file mode 100644 index c091109e..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic-9.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2bfee788708536219614f48af5921e0d8c189a3d2216bf7b4e5d477d1433fdd3 -size 68227 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Alien_Face_159199178.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Alien_Face_159199178.png new file mode 100644 index 00000000..71533426 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Alien_Face_159199178.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30673221186c180d1300da9a68e2057b0e882f2f99cb9774cc00adc6a6e3b6e0 +size 51702 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Female_Face_4018627046.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Female_Face_4018627046.png new file mode 100644 index 00000000..cc840940 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Female_Face_4018627046.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11625aeaa94b560ab1fa4a4e0fee802245f58f18f8dde034c3055d7a7996878b +size 68167 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Female_V2_Face_4637266368.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Female_V2_Face_4637266368.png new file mode 100644 index 00000000..ff328dee --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Female_V2_Face_4637266368.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:300d26848b2d3154f7f16ddab4be7e45c844cdf28d6b16fa3e8d73084e99f808 +size 60428 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Goof_7074661.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Goof_7074661.png new file mode 100644 index 00000000..f205c091 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Goof_7074661.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f42067e4b2569462aab495db464e57f3df532faf37f825a855dff17d6f12d7dd +size 49548 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Male_Face_4018617474.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Male_Face_4018617474.png new file mode 100644 index 00000000..0111baf1 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Male_Face_4018617474.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:86a1e2bd8b5919452b9d60ae32382f00f79125fcc3cea695c5a61d11b61ff548 +size 73502 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Male_V2_Face_4637244809.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Male_V2_Face_4637244809.png new file mode 100644 index 00000000..5c928332 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Male_V2_Face_4637244809.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94e97d37a45cc9bd8bc8d7ce1a8b92c6dbe42af9c0f3a279bd2ce66eb6b523fa +size 60632 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Vampire.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Vampire.png deleted file mode 100644 index 189990d6..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Vampire.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a77252fb2f36e52b6e4d59565cf7e64327523eab4eed00f3ec4a385d50088b0f -size 79923 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Vampire_7074836.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Vampire_7074836.png new file mode 100644 index 00000000..676e2224 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Classic_Vampire_7074836.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:29e57e0f9288833bad9be0fd00324b7485f42aa11613152146608a8118d193c5 +size 49231 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Colon_Dash_Backslash_15471035.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Colon_Dash_Backslash_15471035.png new file mode 100644 index 00000000..cc65562a --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Colon_Dash_Backslash_15471035.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6693c44e06ee31a0419535c8474c8d6edbd34f92e708991b0fee76af1e8c0350 +size 46597 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Colon_Dash_O_7317773.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Colon_Dash_O_7317773.png new file mode 100644 index 00000000..b4bb95f0 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Colon_Dash_O_7317773.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0486f34b54b8a628ccfda29d6c6fcb412db178c1c948ae72c535f17995208f8f +size 48309 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Colon_Dash_Slash_7075469.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Colon_Dash_Slash_7075469.png new file mode 100644 index 00000000..8115ec69 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Colon_Dash_Slash_7075469.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5bc08e1ef2c284198da608fad47fa0f99cc0302a487447a5b9a916df829e42bb +size 49866 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Colon_Open_Bracket_15470193.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Colon_Open_Bracket_15470193.png new file mode 100644 index 00000000..ae6b46be --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Colon_Open_Bracket_15470193.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d96092ca5c29d5f0e83a7558832e912e4d555506b497ae8f8fcd5bf3575ebba +size 41044 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Commando_10527010.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Commando_10527010.png new file mode 100644 index 00000000..adb3012a --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Commando_10527010.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:536a1555722f93082358b00b5d10f04fc0336fb03268cb0c9b073d4a1334bc7c +size 56003 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Concerned_9250660.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Concerned_9250660.png new file mode 100644 index 00000000..8028eb3a --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Concerned_9250660.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ed9b101aee3b32ef85fda890c114290576c71aa021abb15fa3af3312cb53d9a +size 48653 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Country_Morning.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Country_Morning.png deleted file mode 100644 index 867f230e..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Country_Morning.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:52ff07fac529e7787601f4c92343041e1aff1f41be033efba64a88ac2b32b9f2 -size 90810 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Crazy_Happy_45515121.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Crazy_Happy_45515121.png new file mode 100644 index 00000000..f8924202 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Crazy_Happy_45515121.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa058b9bda70fc077b3a279f09d8fbf02d21015e279cccab1cac805f01c8286d +size 65047 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Crazybot10000_554650579.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Crazybot10000_554650579.png new file mode 100644 index 00000000..fb9b8650 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Crazybot10000_554650579.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:939022240169b8ae4c88a964beec9206d12fa2d52bb77797963f08b2776a5e6c +size 60967 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Crimson_Evil_Eye_1016184756.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Crimson_Evil_Eye_1016184756.png new file mode 100644 index 00000000..52d15017 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Crimson_Evil_Eye_1016184756.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ed5604d6dc7b1510071f9d691db6bee1fd2f5a50b7b9b618a8ff7a66a8618e0 +size 67589 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Crimson_Laser_Vision.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Crimson_Laser_Vision.png deleted file mode 100644 index 94731c34..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Crimson_Laser_Vision.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d9b3e91965eea1dc6c5e43b584b152b07374696b362bac09115cf76142b1ac5b -size 78198 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Crimson_Starface.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Crimson_Starface.png deleted file mode 100644 index fd8ad7ab..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Crimson_Starface.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6f938532bd99109d6ed9717e0e1c08b4f01d8174dfb90937fc4cc98a72c43f37 -size 101064 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cuckookrazybot10000_554663025.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cuckookrazybot10000_554663025.png new file mode 100644 index 00000000..c9fbed2c --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cuckookrazybot10000_554663025.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:614f8ad3870a3643873abc38167d062310238fe5d9e05ed00ba46e704ec4ab7d +size 61539 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cute_Kitty_11389441.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cute_Kitty_11389441.png new file mode 100644 index 00000000..895ee242 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cute_Kitty_11389441.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:993dc40bdb10cb8a1189d20fe026f8554c7b13a1e3a30353665af382bd5dbf7b +size 55941 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cutiemouse_15885121.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cutiemouse_15885121.png new file mode 100644 index 00000000..a4f2ebae --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Cutiemouse_15885121.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3c8badc3ffc305758dd3496aef1173cbe732fbccb6cd2a13f29de0e4ce5b5d7 +size 47944 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/D1_16132514.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/D1_16132514.png new file mode 100644 index 00000000..f9299d9f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/D1_16132514.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e9157ae319010d7e4d41876e6c3a74191a36a5ba874e48e23a92f8a21ae15f13 +size 47990 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/D_14812981.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/D_14812981.png new file mode 100644 index 00000000..a4dbb148 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/D_14812981.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f70d4ae562093a94f084af767db7ab23694d6a5ec715bb211389888254bc910 +size 46891 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Daring_8329690.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Daring_8329690.png new file mode 100644 index 00000000..fde089a5 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Daring_8329690.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6337db4ce535199a730225de428768e2b8925bf2a786e1ecf526ab38a5f20418 +size 56798 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Daring_Beard.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Daring_Beard.png deleted file mode 100644 index 60835cd9..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Daring_Beard.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1474e07a0109bb59e65ac9175ddd0e094fb3ec87fa184dfe3fa95ad14089b94d -size 103862 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Daring_Beard_110288809.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Daring_Beard_110288809.png new file mode 100644 index 00000000..86cf5c2c --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Daring_Beard_110288809.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b98d89115d25c66180ee663764fe42efe9b7138b04e594e400934d7ab9341f98 +size 62135 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Dash_Underscore_Dash_15637848.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Dash_Underscore_Dash_15637848.png new file mode 100644 index 00000000..ae917e2b --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Dash_Underscore_Dash_15637848.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9f4276051b1ef9aeee9638e3f688f1aa3000a253b47a88451e4a8b1b5314aefc +size 36138 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Demented_Mouse_12188176.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Demented_Mouse_12188176.png new file mode 100644 index 00000000..afde8f19 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Demented_Mouse_12188176.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c40a5b443d258f5ecc719404b8e9c5275cfc46c14d07334ec2c72ef238484109 +size 52268 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Dequal_17138027.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Dequal_17138027.png new file mode 100644 index 00000000..1aa990d5 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Dequal_17138027.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:45c9b51cbf2fc39cb42281ffb2d52f4b3001801310c5928a51e75d07f612cb0a +size 43933 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Desert_Commando_323191683.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Desert_Commando_323191683.png new file mode 100644 index 00000000..463b4f38 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Desert_Commando_323191683.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e4c97792a22da0503a18a127de86401211454352f2f374f48cd007b4452c0095 +size 60235 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Devil_Nas_X_-_Lil_Nas_X_LNX.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Devil_Nas_X_-_Lil_Nas_X_LNX.png deleted file mode 100644 index aedfb4b0..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Devil_Nas_X_-_Lil_Nas_X_LNX.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8d0afb6ecb80004b7c9fc7ea8167bf20f08c3d08c0e39820459e98875efda2c3 -size 133433 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Devil_Nas_X_Lil_Nas_XLNX_7657657626.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Devil_Nas_X_Lil_Nas_XLNX_7657657626.png new file mode 100644 index 00000000..f8acfc25 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Devil_Nas_X_Lil_Nas_XLNX_7657657626.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e7d1e55913ecc7b4c4f181a7f9b9391b8c2702da2317985558716b55f9d2e05 +size 95602 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Devilish_Smile24k_Goldn_9156271739.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Devilish_Smile24k_Goldn_9156271739.png new file mode 100644 index 00000000..8c311587 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Devilish_Smile24k_Goldn_9156271739.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:215de023ff3a40b1dce881387b3e340cb45e86c6f8cdecacc3149b4306d26c7b +size 93670 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Dexs_Face_807335973.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Dexs_Face_807335973.png new file mode 100644 index 00000000..d96d5384 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Dexs_Face_807335973.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c1304fb19c515567b0dc330c4a5264d1adf783870a4fc3124fc0f78966003dde +size 47375 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Diamond_Grill_Lil_Nas_XLNX_7657627637.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Diamond_Grill_Lil_Nas_XLNX_7657627637.png new file mode 100644 index 00000000..06159ce8 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Diamond_Grill_Lil_Nas_XLNX_7657627637.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ae78985c97a16ec6d49316c4e958c4e39579fbf2a1736cd1aba23ac39ed09e9 +size 91071 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Disbelief_20337343.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Disbelief_20337343.png new file mode 100644 index 00000000..940308ba --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Disbelief_20337343.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a6d204133dfc6eb8e17439df81683103d70e66616a45bb6462f9e0853c141557 +size 52768 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Dizzy_Face_10907551.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Dizzy_Face_10907551.png new file mode 100644 index 00000000..7bedcfa6 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Dizzy_Face_10907551.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bec2d566dffe1a393f95b0b28044540ecb0f38399dd0a8bbf5ffdbf274973b49 +size 47706 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Dollar_Dot_Dollar_10831558.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Dollar_Dot_Dollar_10831558.png new file mode 100644 index 00000000..dd821b80 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Dollar_Dot_Dollar_10831558.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ebfaf3f76d92c0f7d3a23b9db0571c35b40fa71234094fa71e59a26d47a4247d +size 48152 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Downcast_21352013.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Downcast_21352013.png new file mode 100644 index 00000000..8c105b07 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Downcast_21352013.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7de3d59ac861cf56f7416909bd3da43245cad53ccf6531841300a8eaeb372b46 +size 49440 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Drill_Sergeant_141728899.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Drill_Sergeant_141728899.png new file mode 100644 index 00000000..85c98753 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Drill_Sergeant_141728899.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e065a8f71c62414c64d08249952301724942237e008b098985de65ced29d61c6 +size 54986 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Drool_7074893.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Drool_7074893.png new file mode 100644 index 00000000..07064710 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Drool_7074893.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e99a1851a291b8fa2d4497d834ac76ee4fd31cf1d5be401e60f8e5ba56f76ec2 +size 51485 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Drooling_Noob.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Drooling_Noob.png deleted file mode 100644 index 93f690aa..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Drooling_Noob.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3f4ce7bdf84fcd14db38e56bf76a6711bcb93c3984850cc5dc78f0280d1fc573 -size 76610 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Drooling_Noob_24067718.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Drooling_Noob_24067718.png new file mode 100644 index 00000000..bbf73968 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Drooling_Noob_24067718.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a9633573491b799da42e9c8d9b19232e0a48c50b3a08d0a30a8fbf58286b5b11 +size 48778 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Emerald_Archfey_Visage.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Emerald_Archfey_Visage.png deleted file mode 100644 index e0277d50..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Emerald_Archfey_Visage.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3000f4a177567290983248c572bd5bf593c5c2dfa39699396eb76ac286eb075f -size 132495 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Emerald_Evil_Eye_1016185535.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Emerald_Evil_Eye_1016185535.png new file mode 100644 index 00000000..e391722a --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Emerald_Evil_Eye_1016185535.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b8f2bb13c2342a2bc4da7d00e14e5749816101564d7ad5baa29dc90e0701b043 +size 68880 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Emerald_Laser_Vision.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Emerald_Laser_Vision.png deleted file mode 100644 index c8bd5217..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Emerald_Laser_Vision.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7783aa59d1aab4caf9296e1d22e7c2c48afd89e81ae3158e32667952dac114c1 -size 79063 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Emperor.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Emperor.png deleted file mode 100644 index a2cded78..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Emperor.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4d45a44822a5d3fd910cb1dc91853c690c73cebf77ca7ff62de7ff668ad9b178 -size 93737 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Equal_Close_Parenthesis_14817393.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Equal_Close_Parenthesis_14817393.png new file mode 100644 index 00000000..886351c4 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Equal_Close_Parenthesis_14817393.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f0491496b685576f1637c980e41954b6c03a509c8074b32648f55cf1b83e08f +size 44335 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Err_20418658.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Err_20418658.png new file mode 100644 index 00000000..3d882969 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Err_20418658.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2447d000d841ce8fde8d7ac39053dc02bfafe748dcdc50467856d5d2dc72422c +size 43240 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Exclamation_Face_35168581.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Exclamation_Face_35168581.png new file mode 100644 index 00000000..13e1d1fe --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Exclamation_Face_35168581.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6d030902c2a7207914216a14c5f15817a94530acfd4194d241c29e79faeacd6f +size 55999 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Extreme_10831454.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Extreme_10831454.png new file mode 100644 index 00000000..5e036a10 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Extreme_10831454.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb49b2779b809779f81e06598039325db03c81222a0c8ebeef2c32358a98cf3f +size 61540 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Eyes_Of_Everflame_362051773.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Eyes_Of_Everflame_362051773.png new file mode 100644 index 00000000..2952f7f5 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Eyes_Of_Everflame_362051773.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:25f4a9b92e96a9fa081481dfb1d7ffe3cf1c118c6d2bc7067c15a224eb08962f +size 61970 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Eyes_Of_Everfrost_22972723.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Eyes_Of_Everfrost_22972723.png new file mode 100644 index 00000000..4dd2c945 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Eyes_Of_Everfrost_22972723.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6407bc301c1e3cdea7577c64805c7c183d8b505587ea121baccad24a71d9a61c +size 61743 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Fang_7075142.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Fang_7075142.png new file mode 100644 index 00000000..f25fb210 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Fang_7075142.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3b9e8eeadf18b902665506a4281ec2b17f6313fde55e4b4b74acff1824170590 +size 50934 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Fast_Car_22587894.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Fast_Car_22587894.png new file mode 100644 index 00000000..3b4a48d9 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Fast_Car_22587894.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:90aac84424365e5d98e447b0544deadddff3e779c5886d8d9101cf8f430e8a1e +size 62443 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Fearless_7074991.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Fearless_7074991.png new file mode 100644 index 00000000..71e5b955 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Fearless_7074991.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c1c12ccb32caae9f9e963fb99e9c7b5e89d2e5b76b13e45eb2a309ab9b14017b +size 57655 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Finn_McCool.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Finn_McCool.png deleted file mode 100644 index 6f770e47..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Finn_McCool.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:60393a3c594f4a1e96f0b8685c19248fbb37528668ce5d4bf287c1a0692e3d19 -size 83409 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Finn_Mc_Cool_10907549.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Finn_Mc_Cool_10907549.png new file mode 100644 index 00000000..48958ae2 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Finn_Mc_Cool_10907549.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:04b29e306fd415b65677b61423152d93ab14f4c32d7911b36f04572b2c7a57a4 +size 52643 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Freckles_12145366.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Freckles_12145366.png new file mode 100644 index 00000000..71da7f1b --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Freckles_12145366.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df80e981e87c3403557b73b32a46702d15d2cf1b7114564a78a7bf95b0245657 +size 55862 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Friendly_Cyclops_30394438.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Friendly_Cyclops_30394438.png new file mode 100644 index 00000000..3d6494eb --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Friendly_Cyclops_30394438.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f9cc44c4a40a996773e707fca0f8435f2de8bf4a49514dbab4a96c40529a764 +size 61081 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Friendly_Grin.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Friendly_Grin.png deleted file mode 100644 index 575cbe8f..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Friendly_Grin.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7a7ee2340d40ae473ae0456f43ae8c78d541316caa30ce5f08eb37c14a9cc045 -size 79812 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Friendly_Grin_25321961.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Friendly_Grin_25321961.png new file mode 100644 index 00000000..dd80dafe --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Friendly_Grin_25321961.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21df8fe7d8f2f5d0ac3fc9d12559a24c93e7cb8a3da4cb0d3f2721403c29c6bc +size 52359 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Friendly_Pirate_19366445.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Friendly_Pirate_19366445.png new file mode 100644 index 00000000..152bd358 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Friendly_Pirate_19366445.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:856751af8794a25b5d6f4d34f4d9454b71fb43096fa7dc2738f0cff1649564ac +size 59069 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Friendly_Smile_616381207.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Friendly_Smile_616381207.png new file mode 100644 index 00000000..ff2cb318 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Friendly_Smile_616381207.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4df653e7dcff2fc1b721e01df8ba959ee15acd903630c801b10479a8a86a3392 +size 62174 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Ghostface_12467159.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Ghostface_12467159.png new file mode 100644 index 00000000..4a56743f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Ghostface_12467159.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:91d6ff5a24dedef28f6f7e40d08ab6ff031f73f2d1082e70552b4433661483bc +size 51334 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Gigglypuff_35397243.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Gigglypuff_35397243.png new file mode 100644 index 00000000..6864d7ed --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Gigglypuff_35397243.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:70301f91d5971ae40947d22be5980aec1221b4efe141d424eab30a574d1b98a1 +size 52764 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Glee_7074729.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Glee_7074729.png new file mode 100644 index 00000000..8e5a1cc8 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Glee_7074729.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9612680fab0102745e22c551fa5d303e7bb8e863007fb33ebf02478eff7db19c +size 54475 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Glittering_Eye_Zara_Larsson_7893460486.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Glittering_Eye_Zara_Larsson_7893460486.png new file mode 100644 index 00000000..c18dbeac --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Glittering_Eye_Zara_Larsson_7893460486.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d3cc4ce7e9907bd8b08bc32ab380ca1c6958fff53d4be3f51055ac0ec72e7dad +size 144030 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Glory_On_The_Gridiron_21802396.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Glory_On_The_Gridiron_21802396.png new file mode 100644 index 00000000..bf06686d --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Glory_On_The_Gridiron_21802396.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f7f57676a818e8d50f543a6ec4e787e194f5b441d21ab1df7133144c690cca31 +size 58714 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Gold_Mermaid_Visage_5122245866.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Gold_Mermaid_Visage_5122245866.png new file mode 100644 index 00000000..6fadfee1 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Gold_Mermaid_Visage_5122245866.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:82be84ba770944ccf3a23b1603c72662ce19a689a7621c4c8d6889cdd1a90522 +size 88345 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Bling_Braces.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Bling_Braces.png deleted file mode 100644 index 6ae97e88..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Bling_Braces.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:558b6590a38a79f9d9cc2d9f5f39d2d75452feda67508515b23bf653b6d03116 -size 91576 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Evil_Eye_1016185809.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Evil_Eye_1016185809.png new file mode 100644 index 00000000..616143e9 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Evil_Eye_1016185809.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:313981c83dda3b50bb2aabf11773f1390227e4bb755900a66b9efc960ffcca10 +size 68672 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Eyes24k_Goldn_9156275069.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Eyes24k_Goldn_9156275069.png new file mode 100644 index 00000000..b3b422b3 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Eyes24k_Goldn_9156275069.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:839805fe70dc76ab6dfaaf5cb77e321aa780dc56f98f6fc1e4f7ac675341ec29 +size 131718 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Lightning_Speaker.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Lightning_Speaker.png deleted file mode 100644 index 2b753161..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Lightning_Speaker.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f733527aff5389c338ab375124aa7fe40705dea344e3fedf26467d47084ce49e -size 82787 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Shiny_Teeth.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Shiny_Teeth.png deleted file mode 100644 index 2100a79b..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Shiny_Teeth.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c923b25cd1a4e5b6add532e019692881c3124412a0654616fed0543e3f4dd143 -size 93287 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Shiny_Teeth_66319941.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Shiny_Teeth_66319941.png new file mode 100644 index 00000000..ccd0ba6b --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Golden_Shiny_Teeth_66319941.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fbd06804524a6fd79e224971dcd4cc516469e77b236e6077ac8a43f08980e52b +size 59403 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Good_Intentioned_7317793.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Good_Intentioned_7317793.png new file mode 100644 index 00000000..2c1242e2 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Good_Intentioned_7317793.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37cd62487fd9545a4c997bc171b7d0c3cfa56127e7ec01786a3023646a58147c +size 56243 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Goofball_27134344.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Goofball_27134344.png new file mode 100644 index 00000000..fc5c5970 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Goofball_27134344.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:770e2c67e58c5b229f9a31c426686fa722c76297377a7bf129387639c43feb16 +size 73559 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Greater_Than_Underscore_Less_Than_15324577.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Greater_Than_Underscore_Less_Than_15324577.png new file mode 100644 index 00000000..1ebfd676 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Greater_Than_Underscore_Less_Than_15324577.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b975cf25292a7eacd42454abd54d4a795d93d7752b42bf82ae41cbf11b30b399 +size 44037 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Amazeface.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Amazeface.png deleted file mode 100644 index 37afbd30..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Amazeface.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:aabb21c9096976bf24c12169404b4bfce8a5cbb580f178e6931b86ca421679f3 -size 95976 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Amazeface_835094544.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Amazeface_835094544.png new file mode 100644 index 00000000..b619e872 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Amazeface_835094544.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:38723b614e743f47224cee3525999bb850dbdf018e190ade697b34c583ad83ad +size 63527 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Bubble_Trouble_380754227.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Bubble_Trouble_380754227.png new file mode 100644 index 00000000..c2f4b2db --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Bubble_Trouble_380754227.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd20e728d46a42eb147e268c9b520b3f51d11dca5163083ba445bec737c6cb8d +size 61699 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Drool_Angry_Zombie.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Drool_Angry_Zombie.png deleted file mode 100644 index c40a0680..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Drool_Angry_Zombie.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:34aa316d29cdc8d9c417918c425de99d0f77f14d00061b4aef012b739d20802e -size 94387 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Glowing_Eyes.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Glowing_Eyes.png deleted file mode 100644 index e71d61cc..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Glowing_Eyes.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:65fe11e2024c0a9db8d3eca161c9a9d5c741c05d56104a2140dc7b13fb79e917 -size 88864 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Goof_1191162539.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Goof_1191162539.png new file mode 100644 index 00000000..fd129bc9 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Goof_1191162539.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a623f73921322c44c850a0e19c1d0b99ab3895365e24d701b9744de08313a14d +size 68938 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Starface_119812738.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Starface_119812738.png new file mode 100644 index 00000000..e2f1b6ab --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Starface_119812738.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9b4b5d4ccf7e80d8009af0e3973970167501fd9169360fd58a934ca9906007e3 +size 65812 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Starry_Sight_2222774106.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Starry_Sight_2222774106.png new file mode 100644 index 00000000..0fafd33c --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Starry_Sight_2222774106.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a29ec902961328d47b081184feeb54e6521362cca3bdde7cc853fee80e265f17 +size 63611 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Trance_260303894.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Trance_260303894.png new file mode 100644 index 00000000..7d511573 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Trance_260303894.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8554fee09ce1ca7da75ecd0fab68ae5d42c4fd336324e80a3b7b16aadbf78b6b +size 65055 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Ultimate_Dragon_Face.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Ultimate_Dragon_Face.png deleted file mode 100644 index 068a5daf..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Ultimate_Dragon_Face.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:11d471a9b053d5d361635895b22ca90204ddc145330655104ca6f78ebfd954be -size 115436 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Ultimate_Dragon_Face_1772531407.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Ultimate_Dragon_Face_1772531407.png new file mode 100644 index 00000000..cd3a4867 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Ultimate_Dragon_Face_1772531407.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b64498772900b9220a919f2a4f2fef84a8b2e52341a07dae41e0fb7055b9c67f +size 77054 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Whatchoo_Talkin_Bout.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Whatchoo_Talkin_Bout.png deleted file mode 100644 index 739f3061..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Whatchoo_Talkin_Bout.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bd7b496b6983add2b486f2007110f790d4219b7005eb31b4c065763e01e64a29 -size 85376 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Wistful_Wink_583722932.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Wistful_Wink_583722932.png new file mode 100644 index 00000000..84ae7d5b --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Green_Wistful_Wink_583722932.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cfe65a8f89a68fbcfbe92814e6bfa0bb82f078f707c2d584f1d291d0532e86ef +size 56895 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Greeneyed_Awesome_Face_66330144.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Greeneyed_Awesome_Face_66330144.png new file mode 100644 index 00000000..22342ffc --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Greeneyed_Awesome_Face_66330144.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2df51e046b1b4f3852d1caec9e7a724019c17c338839195096a227a59a2298a0 +size 65729 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Gritty_Bombo_406000562.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Gritty_Bombo_406000562.png new file mode 100644 index 00000000..7b74df3e --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Gritty_Bombo_406000562.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0919a7becf7fb16bc8d573b023323c15bb73caf915f53bc353c39be4f0b4ba2e +size 83984 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Grr_19398554.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Grr_19398554.png new file mode 100644 index 00000000..c88fdac5 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Grr_19398554.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:80752d9f92bab31614eeefa29181bccd61963fab6a51ba0146fc8e1e74efe282 +size 54041 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Happy_D_406000730.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Happy_D_406000730.png new file mode 100644 index 00000000..d3a19af6 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Happy_D_406000730.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f06580fe487ef7b8d415e35b2f9c1edc32198eb33e6e962cceafb948673144f +size 46378 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Happy_Girl_Face_293226229.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Happy_Girl_Face_293226229.png new file mode 100644 index 00000000..d329e16f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Happy_Girl_Face_293226229.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:97a894d7355894a84d0c77d253cc32d55fa918533eb2b89572b01b6dc3e0928a +size 56429 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Happy_Wink_236399287.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Happy_Wink_236399287.png new file mode 100644 index 00000000..b0d6359f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Happy_Wink_236399287.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a33981e40f2e6cb71db67c32a86f200952ac4467937d22641652d3869c691d4 +size 58054 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Heeeeeey_21635565.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Heeeeeey_21635565.png new file mode 100644 index 00000000..bc3b70c1 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Heeeeeey_21635565.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1a50f1df7256bdc2e04cd131d2bb11761a7661144381b05e9e05fc42cc206267 +size 50242 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hehe_18151826.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hehe_18151826.png new file mode 100644 index 00000000..c55f2064 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hehe_18151826.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d91f576e7c362cfdc22795f3c13c863f1c89c3469a353bb90313a181daf9c1c9 +size 40477 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hilarious_27861352.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hilarious_27861352.png new file mode 100644 index 00000000..8d6d09de --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hilarious_27861352.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:635ba91a8789aba3d4ed20244d5d8c30ce5fa2a3232439537bc2e5781533d4ad +size 57163 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hmmm_7076076.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hmmm_7076076.png new file mode 100644 index 00000000..d55aced7 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hmmm_7076076.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ea844fbc150094b6b6c5dd7cf30aa9b2ef6663c3f3e958c3808a1e7d3d9347d +size 46992 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hold_It_In_2222771916.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hold_It_In_2222771916.png new file mode 100644 index 00000000..0246defb --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hold_It_In_2222771916.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:617a198a038af15cf41229f136fe2654e23f2f89925ea2e2bfecb0683fa5f142 +size 49500 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Huh_150182466.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Huh_150182466.png new file mode 100644 index 00000000..cc9999c8 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Huh_150182466.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b8d416018de475923f0bc2a051ca1128cc6cd1323bb01e52d3675a99a04a1272 +size 60560 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hut_Hut_Hike_15470849.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hut_Hut_Hike_15470849.png new file mode 100644 index 00000000..7aefbb39 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hut_Hut_Hike_15470849.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a3eac7b03c30d619435a4efda5bc5de19c21175567db4903950f0fc152841ec3 +size 50248 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hypnoface_10770436.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hypnoface_10770436.png new file mode 100644 index 00000000..81bfc953 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Hypnoface_10770436.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d885619508de1b0f6afc9084548941f6ee36e7f9189754ed5aa02cddc5756989 +size 57011 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/I3_New_Site_Theme_32723404.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/I3_New_Site_Theme_32723404.png new file mode 100644 index 00000000..37eff77f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/I3_New_Site_Theme_32723404.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:624ecfb5bbc312e8619d90cf8a895384b0f6f38e9bace4834a3f7519df4807a2 +size 53549 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/I_Am_Not_Amused_7131886.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/I_Am_Not_Amused_7131886.png new file mode 100644 index 00000000..a7419949 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/I_Am_Not_Amused_7131886.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:106bff454152ef43032ed268a2f9e6c3ee368303b96afb32123ef89c9f049830 +size 56235 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/I_Didnt_Eat_That_Cookie_116042990.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/I_Didnt_Eat_That_Cookie_116042990.png new file mode 100644 index 00000000..a820d443 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/I_Didnt_Eat_That_Cookie_116042990.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3125c5f88c707938b347683d53f2f7bbac8082eaa9fecef4c2d601a41d05174f +size 59502 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/I_Hate_Noobs_14030577.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/I_Hate_Noobs_14030577.png new file mode 100644 index 00000000..f3f4cf70 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/I_Hate_Noobs_14030577.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf12a122b17471d69c95240aa3cff28c27f041f6c6ed6dadcf01180114ed5af9 +size 40719 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/I_Wuv_U_10907545.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/I_Wuv_U_10907545.png new file mode 100644 index 00000000..2e815193 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/I_Wuv_U_10907545.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5475f541c015873ea63c57c0aa73c9015d8c5ca5dcc3253effc7b95acab12c37 +size 56960 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Its_Go_Time.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Its_Go_Time.png deleted file mode 100644 index 562fa31d..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Its_Go_Time.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b5d82b86fe1e7c78adddc93798cca46f87cd8906b28d0286c3f98fbd6214bb79 -size 90585 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Its_Go_Time_7506141.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Its_Go_Time_7506141.png new file mode 100644 index 00000000..d241687e --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Its_Go_Time_7506141.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb1bf35c26618c1a6dbcde50544fa777a43ed0ba40919d65b5e290b19d0ab24c +size 55594 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Jack_Frost_Face_19396123.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Jack_Frost_Face_19396123.png new file mode 100644 index 00000000..0c1db952 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Jack_Frost_Face_19396123.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7f83486775c9082c89098fc3213d8688509ab8ad8aa28d9a5a08a34a15032810 +size 56320 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Joyful_Smile_209995366.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Joyful_Smile_209995366.png new file mode 100644 index 00000000..c2410fa4 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Joyful_Smile_209995366.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f06d2ebe9b5a33b9bb6849518297c6eb1149140d22faedacb0822d7e5da70f40 +size 55433 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Joyous_Surprise_28999228.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Joyous_Surprise_28999228.png new file mode 100644 index 00000000..2ba49747 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Joyous_Surprise_28999228.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1ef47983afc150db4bfc06ee5ced3ea03c5fd8fd348a73b74d8ef80be141d6e +size 56115 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Just_Trouble_244160766.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Just_Trouble_244160766.png new file mode 100644 index 00000000..ef8cba75 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Just_Trouble_244160766.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e16b4953aa59b82874c204900680ad6d84e46737e24ff356670a8bc69dcb9270 +size 52379 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Knowitall_Grin_26424808.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Knowitall_Grin_26424808.png new file mode 100644 index 00000000..5014f07f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Knowitall_Grin_26424808.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4735773ba217bfa3b39ac0851320249deba5cd477df77d2dabf0f86d869b08b1 +size 63418 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Krezak_Face_293309580.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Krezak_Face_293309580.png new file mode 100644 index 00000000..077d80e4 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Krezak_Face_293309580.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:548e1ace96c91a99109895b9e7dc54c886cbde8b72bbb1318b3a6982480258fc +size 46814 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Lady_Lashes_29348122.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Lady_Lashes_29348122.png new file mode 100644 index 00000000..45b97567 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Lady_Lashes_29348122.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1d1eeefe100a52249acf366f3c866bf539efd0a014ecc8bd2d4e5d47852de653 +size 71098 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Laughing_Fun_226217449.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Laughing_Fun_226217449.png new file mode 100644 index 00000000..9becd4f2 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Laughing_Fun_226217449.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2d8b2f5916715187ade53880a475508296e72655a0e4f6c664d1d19e61373d6f +size 54620 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Lavender_Amazeface_835095306.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Lavender_Amazeface_835095306.png new file mode 100644 index 00000000..caf2175f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Lavender_Amazeface_835095306.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21b987b810e7904d9d065853cd708aec62e627b1d93541336362acc002954670 +size 61412 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Lazy_Eye_7075502.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Lazy_Eye_7075502.png new file mode 100644 index 00000000..79d3a7f7 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Lazy_Eye_7075502.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:77d81de229841c393bc312c8af1ce0036f8191659b551977c5e27af9238615d1 +size 46800 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Lightning_Speaker_22588801.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Lightning_Speaker_22588801.png new file mode 100644 index 00000000..add8b8c0 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Lightning_Speaker_22588801.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fec8148470797231bf174a5e666da9621c20a229eec17e16747ebb66e91d7ee6 +size 50585 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Lins_Face_301826803.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Lins_Face_301826803.png new file mode 100644 index 00000000..3ae90a9d --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Lins_Face_301826803.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5aee61d8b8e31a795151964467f6218965e4f13a5c57efa4a56b847e87487495 +size 62744 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Look_At_My_Nose_23311761.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Look_At_My_Nose_23311761.png new file mode 100644 index 00000000..59456545 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Look_At_My_Nose_23311761.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:92e2328f4b4a883980c2b55c68053801681ae644860c45fad0d6fca38aef2242 +size 62957 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Madbot_10000.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Madbot_10000.png deleted file mode 100644 index ae7855c9..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Madbot_10000.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:71671c5e3caa9f8db975b15b7c74a23ad486ae2015bc0c39c8e6b7b166502f2b -size 97017 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Manicbot10000_554663566.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Manicbot10000_554663566.png new file mode 100644 index 00000000..b16a6f03 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Manicbot10000_554663566.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7aaa6140a497d5b47ce94a49d960932d3f65fa56d8fc56b324ce6cf20eee495f +size 60702 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Manlier_Face_76383151.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Manlier_Face_76383151.png new file mode 100644 index 00000000..d871db91 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Manlier_Face_76383151.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3576a876deae9023c07eee36477d2b09aa88cb465d6fdd016326da263d57a546 +size 66778 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Mclaren_Big_Grin_9062637857.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Mclaren_Big_Grin_9062637857.png new file mode 100644 index 00000000..901fe84a --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Mclaren_Big_Grin_9062637857.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:395776032185e5499f9ef515a35f523562c8a55578a2732d83bf1b90797caf91 +size 79328 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Meanie_9250643.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Meanie_9250643.png new file mode 100644 index 00000000..c26bf2c9 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Meanie_9250643.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3355296a3bc8ffa2f774951f3e549bf8f68e226d4e5d4845e684232065dbecb4 +size 49956 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Meow_10907529.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Meow_10907529.png new file mode 100644 index 00000000..96e1e65c --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Meow_10907529.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bcb572452828b9baf6201642832fc20d1bfc858b4d816ff39b668ca7224b9f7d +size 70615 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Monarch_Butterfly_Smile_383607653.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Monarch_Butterfly_Smile_383607653.png new file mode 100644 index 00000000..dc7aa6d5 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Monarch_Butterfly_Smile_383607653.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca7a5c408980d39c80f5aeaec4e368d18004ad7da910e2e598423d569138b6cd +size 63333 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Monster_Face_49045351.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Monster_Face_49045351.png new file mode 100644 index 00000000..ced14c0c --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Monster_Face_49045351.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c34c96a45db120f5ffc8af03273a5afd8a0372d4d10889f952555807e2f95372 +size 51479 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Monster_Smile_398675917.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Monster_Smile_398675917.png new file mode 100644 index 00000000..d84ba075 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Monster_Smile_398675917.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ac01d518dd0d6275dc503e0de5946eb7ea854570537465d467930dc82432264 +size 67802 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Mr_Bubbles.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Mr_Bubbles.png deleted file mode 100644 index 34791958..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Mr_Bubbles.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ee787df8c737b7a0479f51e07564a3a7add8657845a7634e3485ddc26be16d96 -size 91960 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Mr_Toilet_Face_4416933495.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Mr_Toilet_Face_4416933495.png new file mode 100644 index 00000000..8ecdc306 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Mr_Toilet_Face_4416933495.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:995e449ba062f1641be794915440dc075ef190aff1f5759da4742d59d6c54d76 +size 64946 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Mysterious_7132035.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Mysterious_7132035.png new file mode 100644 index 00000000..863081cf --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Mysterious_7132035.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:de3ecfe6e61e716c42ed3b107514f3e59e67483e08dd892645809c217636eae8 +size 46033 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Negation_Underscore_Negation_13038375.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Negation_Underscore_Negation_13038375.png new file mode 100644 index 00000000..67ee69e3 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Negation_Underscore_Negation_13038375.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b67a168d94e9e0c20128e6e74576b9f34a2a92ab961b81fffed300b29f6f44a8 +size 40675 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Neoclassic_Malev2_Face_4637291815.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Neoclassic_Malev2_Face_4637291815.png new file mode 100644 index 00000000..a3c56fe0 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Neoclassic_Malev2_Face_4637291815.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f32802ed5b0824dc2f439a3639e50a1f69781c6b159ab14da2ff4126e8848044 +size 61121 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Nervous_23219981.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Nervous_23219981.png new file mode 100644 index 00000000..c815e06a --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Nervous_23219981.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4152c58409fc2f68506ed33f6906804d9786d047da37b1e20d5d5867f4b51187 +size 49495 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Nethack_Addict_16357383.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Nethack_Addict_16357383.png new file mode 100644 index 00000000..6df449ef --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Nethack_Addict_16357383.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e077fe895f37a17aeb01bb2652d6df31f58c5c9464c29f9b867f0d22d23c4852 +size 53069 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Notsureif_173789324.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Notsureif_173789324.png new file mode 100644 index 00000000..fd52384d --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Notsureif_173789324.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a9c1d0d15de1526a062fa8754acde2dc81aee2ba85b529764fdc34749d81f19 +size 42888 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Nouveau_George_398675764.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Nouveau_George_398675764.png new file mode 100644 index 00000000..90c48f16 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Nouveau_George_398675764.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5581a9453b121940eae2765143c977ff11a60a0c9d3b0847cb42ae9285a2262b +size 51032 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Obvious_Wink_51241537.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Obvious_Wink_51241537.png new file mode 100644 index 00000000..de969004 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Obvious_Wink_51241537.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a9c262d08e51c2f1424297f566da86edbf3c806df3df0cdd81840bcfb82d8bfe +size 54888 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Oh_Deer_12145328.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Oh_Deer_12145328.png new file mode 100644 index 00000000..a6d542cc --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Oh_Deer_12145328.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:34784c697a4c25715b70aa1b19cd8f7f1f3b2562e36854dc7aa77810fcecb3fa +size 63432 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Old_Timer_27003636.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Old_Timer_27003636.png new file mode 100644 index 00000000..06a8df0f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Old_Timer_27003636.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eec3be970ab14de80d24b094d07ea46ad9ebb41d52abe3fde6a6cbafa6c20dc8 +size 65967 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Oo1_7074595.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Oo1_7074595.png new file mode 100644 index 00000000..f01f1162 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Oo1_7074595.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cd4e8417fe9d63e869b1ac683da7f3c125d0680eb985e1faec15a295c5e9fe85 +size 41560 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Oo_66330265.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Oo_66330265.png new file mode 100644 index 00000000..e1382cc1 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Oo_66330265.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af4b4b892d8d57672f579e5d5428bc1eda7abd26ec1eb37b9de06990d9b425a0 +size 53155 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Optimist.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Optimist.png deleted file mode 100644 index 8867b234..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Optimist.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4df1edce1bf5029518fe00cbadbb60ca76c846cae99fcfdcd2913bd375b4c318 -size 87464 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Orange_Starface_162200666.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Orange_Starface_162200666.png new file mode 100644 index 00000000..2ce75289 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Orange_Starface_162200666.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:64f3c158c7d6801d341a68a2d5d18f5f2844cdf86f6c0bbc48fe485daa323cd7 +size 66856 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Overjoyed_Smile_1428416217.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Overjoyed_Smile_1428416217.png new file mode 100644 index 00000000..1f8efba8 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Overjoyed_Smile_1428416217.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1aa8738096c2cbd254d5b331e7288d17e60b62436421d10de7ee4eb2bc0229b3 +size 55031 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/P_14861743.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/P_14861743.png new file mode 100644 index 00000000..b894f56e --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/P_14861743.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa5ccd2f2bccd3a3d1a66f1673506d108958ee474815c28f072c894e2d3d6174 +size 43900 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Paintball_Enthusiast.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Paintball_Enthusiast.png deleted file mode 100644 index 1f552320..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Paintball_Enthusiast.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:948cc98a526082477d20fa6b51ce4f433325823a95c7e15b4f4d6a434f3cf482 -size 114944 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pieface_Jellyfreckles.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pieface_Jellyfreckles.png deleted file mode 100644 index 9127bc3d..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pieface_Jellyfreckles.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0c9e18e1d2a241383f9b6ef53cc96fbd39b68146c08a71cca13e4a207301a788 -size 125759 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pink_Galaxy_Gaze_440738448.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pink_Galaxy_Gaze_440738448.png new file mode 100644 index 00000000..3fa47436 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pink_Galaxy_Gaze_440738448.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3cb9dec0985ceedf15bb44f55505afdd53cf9f1e036d5df4528763053c318a88 +size 60449 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pink_Mermaid_Princess_1428418448.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pink_Mermaid_Princess_1428418448.png new file mode 100644 index 00000000..166a5159 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pink_Mermaid_Princess_1428418448.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0317b26440d7c2b9cfff442a5d98494d68ab5e72a9c0c496e245e57179781696 +size 89764 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pink_Shades_Mccool_323192138.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pink_Shades_Mccool_323192138.png new file mode 100644 index 00000000..e101a1ba --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pink_Shades_Mccool_323192138.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c601206397dfc5254782b8757c95e92d85b51c485d55b0fdc16b80a26f122a7 +size 64151 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pink_Wistful_Wink_583721990.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pink_Wistful_Wink_583721990.png new file mode 100644 index 00000000..4681051b --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pink_Wistful_Wink_583721990.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e12f2f1ac7c81c3f5d46b3bd1de80676dbb75d77e55331f42e70e961191e352 +size 58425 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Poisonous_Beast_Mode.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Poisonous_Beast_Mode.png deleted file mode 100644 index 28c988cb..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Poisonous_Beast_Mode.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0b219d9ec49099a05fa1eef986ec9b2034ae767a17a54d60ee41ea9aa92db0d5 -size 103863 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Poisonous_Beast_Mode_2606177838.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Poisonous_Beast_Mode_2606177838.png new file mode 100644 index 00000000..69b6dbc3 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Poisonous_Beast_Mode_2606177838.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fab20d05ab661fe2f708613a0bf744b6d3dde14219f199218021724d5486c690 +size 70189 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Prankster.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Prankster.png deleted file mode 100644 index 8716a56a..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Prankster.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4910bddcf8b1e561c01f2817c4253edada6a92a5d7b27e6d42336c2b1f5c5f88 -size 100876 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Prideful_Smile_3267564334.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Prideful_Smile_3267564334.png new file mode 100644 index 00000000..69ef883d --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Prideful_Smile_3267564334.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8c3933bd462aba513231d41d0c9f359b114e010a5f399e289f4f14d810dfaff +size 88865 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Puck.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Puck.png deleted file mode 100644 index 7a28db59..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Puck.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1492e0218aaa2b4a7aca0de3e20b671b801e35f22a16882554d30484d49a649d -size 76880 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Puck_20298988.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Puck_20298988.png new file mode 100644 index 00000000..fa71f881 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Puck_20298988.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79998db2a2f56809980af58232f8f20280aa2e8d0d0c576c0a4e15b1cf61d351 +size 49474 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pumpkin_Face_313549781_313549781.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pumpkin_Face_313549781_313549781.png new file mode 100644 index 00000000..acff2b03 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pumpkin_Face_313549781_313549781.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b46e13bc49da89c38a918e345a0e561bab3d0ff40953b897ab4482c007ab5b1 +size 50719 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Punk_Face_119812659.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Punk_Face_119812659.png new file mode 100644 index 00000000..2525678e --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Punk_Face_119812659.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:364cb846cdaba9983f6fd79f6b329bf97f9eee115665b00a1e64539653eb7d14 +size 58238 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Bubble_Trouble_362051999.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Bubble_Trouble_362051999.png new file mode 100644 index 00000000..d1c8762e --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Bubble_Trouble_362051999.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd92bcfdacb32041cf4a822b1b62fc9252f5f577ccdeaaf5d2299fbc7814b68e +size 61905 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Butterfly_Smile_238983270.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Butterfly_Smile_238983270.png new file mode 100644 index 00000000..401632d5 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Butterfly_Smile_238983270.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24528979cf63a059b398c4ae0f59a327b2e3544abd51e66a9d662548a4ff9071 +size 62720 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Mermaid_Princess_1428424821.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Mermaid_Princess_1428424821.png new file mode 100644 index 00000000..8c2699bf --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Mermaid_Princess_1428424821.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df7f696430fb7185c254ccab2de901f8bb51501fc2b75faa38a9a9a84225911c +size 84938 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Moonstruck_878942257.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Moonstruck_878942257.png new file mode 100644 index 00000000..5e78c1e6 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Moonstruck_878942257.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cab4e75c84e6e24778d50fdd20fed0e2d52844dc6c53cf136a5758b65e1b0913 +size 61716 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Trance.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Trance.png deleted file mode 100644 index 8d29fc95..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Trance.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e72b5cd2e865863f0775b6bee47cb300e816db9b82d68de8641b08c8cb0418af -size 94011 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Wistful_Wink_583722710.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Wistful_Wink_583722710.png new file mode 100644 index 00000000..94c056f1 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Purple_Wistful_Wink_583722710.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:54a8d76875c49bcf5fa069e714ace14298a6336a79004cffa8b19209478af696 +size 56703 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pwnda_Face_28281786.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pwnda_Face_28281786.png new file mode 100644 index 00000000..1965c838 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Pwnda_Face_28281786.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8ff9e2e217e9e91e204b59e8728a65175a91feb35f0eb5654816b803226cd00f +size 67399 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/ROAR_406001167.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/ROAR_406001167.png new file mode 100644 index 00000000..156ee66d --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/ROAR_406001167.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:db6e3287937df8720e2250c85a4fbaa0247750a7741141ae80fafc723651b575 +size 52809 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Radioactive_Beast_Mode_2225761296.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Radioactive_Beast_Mode_2225761296.png new file mode 100644 index 00000000..ee462f96 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Radioactive_Beast_Mode_2225761296.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a20930fba150a60dd4847ca8e42d4308a856574c4d6638ff0393533b0786cb61 +size 68713 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Raig_Face.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Raig_Face.png deleted file mode 100644 index 6e40d597..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Raig_Face.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:50c41d3b4848c2c831812fa65f5a139b03cc392c402ee427d29015971f00eccf -size 88115 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Raig_Face_209994783.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Raig_Face_209994783.png new file mode 100644 index 00000000..2c9c6517 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Raig_Face_209994783.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f6bfc23002a61c057e4cf5a007e4724f69b4f58b51fcd31720981590d2df2d29 +size 58558 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Rawr_7076224.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Rawr_7076224.png new file mode 100644 index 00000000..a15db83d --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Rawr_7076224.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cce7d05eeebf51f62227e68348303954ea4c1973340ca3c99fc2827a34d85dff +size 52398 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Really_Embarrassed.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Really_Embarrassed.png deleted file mode 100644 index c16be29c..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Really_Embarrassed.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:94ec9e9f52facdef28d0fe659f188f53d67c842a97c30f9a4d74a3e562f70b15 -size 106190 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_Glowing_Eyes.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_Glowing_Eyes.png deleted file mode 100644 index 57db785f..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_Glowing_Eyes.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8371ce6408f08a1ec1f683faf9c4e20be3d630df6fa5ceb1c5f3abae44b9cad3 -size 88564 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_Goof_1191125008.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_Goof_1191125008.png new file mode 100644 index 00000000..67795dd7 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_Goof_1191125008.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:497d7a2f679ef3b97472d5b4af7842dec170d94936a94e1023bc76ae1bc4bcec +size 69256 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_Lip_-_Tate_McRae.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_Lip_-_Tate_McRae.png deleted file mode 100644 index d011803d..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_Lip_-_Tate_McRae.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:25f8250231457ade56973fb6e2c67b95d8cd9bd5e1bd7df08658c1a400503899 -size 138986 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_Lip_Tate_Mc_Rae_9650713776.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_Lip_Tate_Mc_Rae_9650713776.png new file mode 100644 index 00000000..4c712415 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_Lip_Tate_Mc_Rae_9650713776.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7fbd60124121de8c877aaedc1ca6623ae7de0b87af0cc54a2eb6576e14b6e722 +size 92798 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_Ultimate_Dragon_Face_1772530315.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_Ultimate_Dragon_Face_1772530315.png new file mode 100644 index 00000000..4c941955 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_Ultimate_Dragon_Face_1772530315.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c908511dea98e08e2c98d5f8e1b43676c1d34aae7d1eba5b761f676ade51dd22 +size 78729 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_White_And_Starface_445117183.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_White_And_Starface_445117183.png new file mode 100644 index 00000000..68324ed4 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Red_White_And_Starface_445117183.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:694548c5e0a2a3834d4a8344b1e9ddc80e961d5d89b0cd400d270478f34f71b0 +size 63523 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Retro_Smiley_10770432.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Retro_Smiley_10770432.png new file mode 100644 index 00000000..034752b6 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Retro_Smiley_10770432.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa9d61172c271ecfd0b08b62166831775cebafdca61e17791760f13dcd4729a9 +size 38903 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Robot_Smile_30265169.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Robot_Smile_30265169.png new file mode 100644 index 00000000..58076022 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Robot_Smile_30265169.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2b2d2b1ee3c05892e2c807284b4f3288af7eb08aca7ad5f8d9feef502bf11209 +size 55756 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Rodeo_Vampire_Lil_Nas_Xlnx_5917448278.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Rodeo_Vampire_Lil_Nas_Xlnx_5917448278.png new file mode 100644 index 00000000..e007a53a --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Rodeo_Vampire_Lil_Nas_Xlnx_5917448278.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ecd1841ca7d5f62462866ccd02e62eba0483093273b87c9083cfceebc3cc3a5 +size 61014 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Rogueish_Good_Looks_1665511048.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Rogueish_Good_Looks_1665511048.png new file mode 100644 index 00000000..68e65363 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Rogueish_Good_Looks_1665511048.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3301fceaf09d718f508f24329bd51f693e0dfbe83efd4e694d1c9f111cecb98c +size 47397 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Rose_Amazeface_835095880.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Rose_Amazeface_835095880.png new file mode 100644 index 00000000..a1ba963f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Rose_Amazeface_835095880.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11031f541cc6ed625f7f16b15813c5ae7102781913f06f3790374ba17d907b20 +size 62387 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Ruby_Archfey_Visage_2830505884.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Ruby_Archfey_Visage_2830505884.png new file mode 100644 index 00000000..03b34e27 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Ruby_Archfey_Visage_2830505884.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26c0bf9ce63a8d39aef54b680a465d9954c8c7889e12054e3e8630601fb8b9a5 +size 86442 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Rudolph.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Rudolph.png deleted file mode 100644 index 7e3595f6..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Rudolph.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:25694f89a13a8a1bacf8ff9585cc3b8c0bf7ad76cea293cd6d3a911c9b4c555b -size 99821 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sad_7699177.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sad_7699177.png new file mode 100644 index 00000000..63a7fc19 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sad_7699177.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f97aeb85e09e7f478377f50ab2f21a58d298cdd487ca4068a76781aaea038780 +size 50874 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sad_Clown.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sad_Clown.png deleted file mode 100644 index 55b7b9dd..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sad_Clown.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1c98942afe84d89e98b657283ba314306e485a288509f2abed969009412cb12f -size 100874 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sadfaic_117522793.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sadfaic_117522793.png new file mode 100644 index 00000000..ba72901c --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sadfaic_117522793.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75aa04737d45e1c88eab35c0044d4614fde8c659ad5e57620ae98ad029f48244 +size 53248 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sapphire_Evil_Eye_1016184964.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sapphire_Evil_Eye_1016184964.png new file mode 100644 index 00000000..34a4b71a --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sapphire_Evil_Eye_1016184964.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0924b776ec44c16d0ff863d29c9dce39938dd7443c0d005acecf5e46435fc59d +size 68448 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sapphire_Laser_Vision.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sapphire_Laser_Vision.png deleted file mode 100644 index d9150ba0..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sapphire_Laser_Vision.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dec5fb475030305d5384015b870e9d29c63b309b6e4e9ccdd968dcf8bd37281a -size 76884 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Scarecrow_26260927.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Scarecrow_26260927.png new file mode 100644 index 00000000..fb71a6a8 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Scarecrow_26260927.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4024f61e6ed5834bb7ac6b70122feeb83135b143e892114019bdd2526d23e276 +size 50951 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Scarecrow_Face_14721869.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Scarecrow_Face_14721869.png new file mode 100644 index 00000000..e9f019f7 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Scarecrow_Face_14721869.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a91f7d182c339cb3180303a07730b4ffcfa79abb985d2a554f4b7439109f0eb +size 53452 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Secret_Service_20612949.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Secret_Service_20612949.png new file mode 100644 index 00000000..fecf5f4c --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Secret_Service_20612949.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b324cd46e6a0e35a59438ecba3f9a9fc32654fc140b3d9a7992b4636a62cd565 +size 49049 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Semi_Colon_Open_Paren_16179646.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Semi_Colon_Open_Paren_16179646.png new file mode 100644 index 00000000..436706d6 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Semi_Colon_Open_Paren_16179646.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5317db292dd26c161e8b5c8da3207ddd7efc241ea70110c301fb3b300a7e8726 +size 49704 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Serenas_Face_301826957.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Serenas_Face_301826957.png new file mode 100644 index 00000000..3a2748c3 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Serenas_Face_301826957.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df8fcf5657d958292722eb4474e3cb0289e0dc4a9a8aceb2faa81b7dafe420f4 +size 59603 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Serious_Scar_Face_255827175.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Serious_Scar_Face_255827175.png new file mode 100644 index 00000000..03c1265d --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Serious_Scar_Face_255827175.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2781023c6429248248ca181b920d6df14582141d506068edd536446c3f6f6950 +size 49193 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sharpnines_Face_Of_Disappointment_209994270.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sharpnines_Face_Of_Disappointment_209994270.png new file mode 100644 index 00000000..6aa6b095 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sharpnines_Face_Of_Disappointment_209994270.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:66714ba3eb97c088761ca85014aa8cad3a03297518704a4327c1439fe470e7a2 +size 51688 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Shocked_147144644.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Shocked_147144644.png new file mode 100644 index 00000000..376c9fbf --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Shocked_147144644.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:92ea01fc83dc0d9f820183e386a830baebb018bf181b77a4707dbe1ea2ba25bf +size 52444 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sick_Day_26619096.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sick_Day_26619096.png new file mode 100644 index 00000000..2b4a0668 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sick_Day_26619096.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2dd808b6cc5e07118e8f7cef2c7e549b3633acd54f1e620f9df16d662daa157b +size 54334 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sigmund_21311601.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sigmund_21311601.png new file mode 100644 index 00000000..757159c2 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sigmund_21311601.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8fa22887fe3b32294082d1f339cd52c54fd0530a2dc56ee48fc092b666581c75 +size 50195 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Silence_10860397.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Silence_10860397.png new file mode 100644 index 00000000..0160d3a7 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Silence_10860397.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:048302ebb272c53b94ecb4ab7f51181779084926ad5465eae43ce178d8d3c081 +size 46836 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Silly_Fun_7699174.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Silly_Fun_7699174.png new file mode 100644 index 00000000..5a010f7f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Silly_Fun_7699174.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a475ed5fbeaa24593c530d45029f09db33389d5a166bc37c15bd30b0157aa34 +size 49313 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Silver_Punk_Face_387256603.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Silver_Punk_Face_387256603.png new file mode 100644 index 00000000..a7a2d15e --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Silver_Punk_Face_387256603.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:40e80c2f6ecd85485d3d65e5f243b3725f1540d36cac82af0952193d6ee720eb +size 57416 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Singing_66330310.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Singing_66330310.png new file mode 100644 index 00000000..32670c38 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Singing_66330310.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:671231e5431989883cd2e263783ac77f6a78518a3a47b1463d6e9db711943ff2 +size 47395 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sinister_8329686.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sinister_8329686.png new file mode 100644 index 00000000..d265e848 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sinister_8329686.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6196236abae87e68ae5b8e94259c51988b46747d918e8b75d1052774ee826d83 +size 51349 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Slickfang_7317765.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Slickfang_7317765.png new file mode 100644 index 00000000..f31e66d3 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Slickfang_7317765.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9b021f7187b71a3333984a3af97fcfe4077e1e80666058c4fad010e5025f18fa +size 55735 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Slithering_Smile_2830646491.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Slithering_Smile_2830646491.png new file mode 100644 index 00000000..3730c487 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Slithering_Smile_2830646491.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7713e32bea5d9b23111ad78dc5732796aa57119d1b82116d0dd1c59af6ded5cf +size 119461 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sly_Guy_Face_238983378.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sly_Guy_Face_238983378.png new file mode 100644 index 00000000..d78aa340 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sly_Guy_Face_238983378.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5166f3057e5534720989d95dfa82c5e1d6b2c80b54d971a30301fa42741c480e +size 49977 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Smil_Nas_X_Lil_Nas_XLNX_5917459717.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Smil_Nas_X_Lil_Nas_XLNX_5917459717.png new file mode 100644 index 00000000..e8dd2f93 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Smil_Nas_X_Lil_Nas_XLNX_5917459717.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:314c38e5d7bd640f1638268bec5fea9a5dce9737db591d9d0d6e2c5b62ab1d18 +size 69581 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Smiling_Girl_209994875.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Smiling_Girl_209994875.png new file mode 100644 index 00000000..19a960b5 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Smiling_Girl_209994875.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f53594ba1ee7c69da4ba5693a7be47a4997389d1017947de75769a290517372 +size 58691 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Smith_Mccool_27412825.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Smith_Mccool_27412825.png new file mode 100644 index 00000000..c5fc03f3 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Smith_Mccool_27412825.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7c8618b04f208a37be86a6bdc6c991ca09fd7b0c300a65e605082d7927346386 +size 59003 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Smug_406001308.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Smug_406001308.png new file mode 100644 index 00000000..24bb31de --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Smug_406001308.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0c480fbda0484ad490b476981eb6dec7274b9bb4c8bfdb5b20691b84d539bad +size 51503 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sneaky_Steve_823012694.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sneaky_Steve_823012694.png new file mode 100644 index 00000000..875fdd13 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sneaky_Steve_823012694.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2b8d878f837637483b07e77739e6b63635061d8add154b892fc968bc4dcaef81 +size 53072 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sniffles_14516578.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sniffles_14516578.png new file mode 100644 index 00000000..2dfc7a48 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sniffles_14516578.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0932169d806947b75959f4ea7e96f6685c358ac6b5d22302e6a909303f325766 +size 47958 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/So_Funny_32058239.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/So_Funny_32058239.png new file mode 100644 index 00000000..1e58424f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/So_Funny_32058239.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5447a95ce29634ee84a8b61b963d7e7c571950a9c6ea6ee6254bac889527b203 +size 53466 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/So_Super_Excited_Blue_2569001052.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/So_Super_Excited_Blue_2569001052.png new file mode 100644 index 00000000..955d347f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/So_Super_Excited_Blue_2569001052.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a187c8d983258b754af27d8afbf13b850eeeb2dabb75252f0998c2507fdb8a3 +size 59138 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/So_Super_Excited_Pink_2568801198.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/So_Super_Excited_Pink_2568801198.png new file mode 100644 index 00000000..331124bd --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/So_Super_Excited_Pink_2568801198.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05f67c1f41fb470b127bf1ff74551efc49d48dfad631e541956c0737d5acb9f5 +size 62327 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sparkle_Time_Sparkle_Eyes_2620507161.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sparkle_Time_Sparkle_Eyes_2620507161.png new file mode 100644 index 00000000..b04cd604 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sparkle_Time_Sparkle_Eyes_2620507161.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cb724573dbd7a7d931e621c1a48c02245a63392a0876ab18f88204e2351a2cfa +size 61947 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Spring_Bunny_110207437.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Spring_Bunny_110207437.png new file mode 100644 index 00000000..ad3bd39c --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Spring_Bunny_110207437.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1a17f53c090b248f323f4794e088245c27ea437c4b9a687b660ebb43be1c3fb3 +size 69645 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Square_Eyes_22119034.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Square_Eyes_22119034.png new file mode 100644 index 00000000..72d7da4d --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Square_Eyes_22119034.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe21f60dcb81d5134646028b2f491b400ace39d2ef5e092a1f1505ee68447bcd +size 57412 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Squiggle_Mouth.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Squiggle_Mouth.png deleted file mode 100644 index 8e4ef977..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Squiggle_Mouth.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:51db718bacbe609ac1af5a84dd51bcb2a632ce838344bc4f457fdf63df1f26fd -size 86836 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Squiggle_Mouth_25166274.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Squiggle_Mouth_25166274.png new file mode 100644 index 00000000..b3ac8a85 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Squiggle_Mouth_25166274.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f7fa8526753a33147eb18548dd4d8b02f5c0057101e42d521c8ff278451beab9 +size 56802 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Squinty_Assassin_Face_880474146.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Squinty_Assassin_Face_880474146.png new file mode 100644 index 00000000..896bb3ee --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Squinty_Assassin_Face_880474146.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a3f4db8311f2afb93342a8447b4544ba0db3413e7865b3a8b5fcd6ec25ab715 +size 51264 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Stare_8560971.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Stare_8560971.png new file mode 100644 index 00000000..b5974978 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Stare_8560971.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a46cd491c2d4f8b2b96351dace43bee3bd995bfbf2c8b35d5661330ae3ba94cc +size 42001 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Starface_32873408.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Starface_32873408.png new file mode 100644 index 00000000..503d3855 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Starface_32873408.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb86e4779188f1a2874d666440e98067190f44c9fa3f84fa00beac116710dcef +size 64866 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Stink_Eye_416846143.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Stink_Eye_416846143.png new file mode 100644 index 00000000..615670e2 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Stink_Eye_416846143.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:07572c0dc671cb1430e0ce9dd3a02a957e1e6e42dffd600ddd2092d8e053dd5b +size 51976 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Stitchface_8329679.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Stitchface_8329679.png new file mode 100644 index 00000000..8d3b9fee --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Stitchface_8329679.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:870d368ea47f4bc16db59d655762ef22f2ee58ec52970383c119fb0b628dc42b +size 56522 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sunny_Fun_51241171.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sunny_Fun_51241171.png new file mode 100644 index 00000000..210db5bf --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sunny_Fun_51241171.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:73cd4fa335b16a9f04c6bfee7f4993f36cfbc01bd476dd3fe45bce9c9b56d992 +size 64838 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sunrise_Eyes_Tai_Verdes_7987201392.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sunrise_Eyes_Tai_Verdes_7987201392.png new file mode 100644 index 00000000..069727a4 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sunrise_Eyes_Tai_Verdes_7987201392.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:986fd932325e4c65607f1fe00c57675ac23a6622d0b23b9691a22312108d92f9 +size 120743 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Super_Happy_Joy.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Super_Happy_Joy.png deleted file mode 100644 index fc6b4588..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Super_Happy_Joy.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:232b9ee7ec297109a46c68aa95727899f580b3413cd1792573f1f42780d51792 -size 98661 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Super_Happy_Joy_280988698.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Super_Happy_Joy_280988698.png new file mode 100644 index 00000000..17327404 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Super_Happy_Joy_280988698.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af4e503d2ef43ad173de65cdab187d1d182196182947b7d11a5885dc862affa6 +size 70925 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Suspicious_209994929.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Suspicious_209994929.png new file mode 100644 index 00000000..0db2e555 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Suspicious_209994929.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0363e753d8246b2af6cafb7ff4be194881d2c91abd7e2051da16623ac24ab39a +size 50481 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sweat_It_Out_20909103.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sweat_It_Out_20909103.png new file mode 100644 index 00000000..ab803743 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Sweat_It_Out_20909103.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f947f8067da3685e1cecc4d77a0a904cfccee8c4a7a928987ff919ebdc3e2e0c +size 54120 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Tango_16101765.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Tango_16101765.png new file mode 100644 index 00000000..6eb64d94 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Tango_16101765.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:80132ac621458012438437c2c5ecdb35f8697b288948ffe58e3679c21cae9610 +size 51114 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Teal_Rock_Star_Smile.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Teal_Rock_Star_Smile.png deleted file mode 100644 index 6f52764b..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Teal_Rock_Star_Smile.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6621523580d4b1da313a282050b003b7a3dd7a43fcbdb968a7538f9c4801e86d -size 96178 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/The_Big_Dog_10860384.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/The_Big_Dog_10860384.png new file mode 100644 index 00000000..f427b8b1 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/The_Big_Dog_10860384.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:83558cf7c987198222c44d0ee9aed7d35eaf6f1b8c9dcadad08e8095c81308c6 +size 68538 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/The_Dog_Whisperer.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/The_Dog_Whisperer.png deleted file mode 100644 index 5d497e61..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/The_Dog_Whisperer.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d4697b4c8bc97c87e95a9d1670590728f8620d589fde5ff7a9a81b9d9475b95e -size 95045 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/The_First_Time_I_Ever_Played_ROBLOX.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/The_First_Time_I_Ever_Played_ROBLOX.png deleted file mode 100644 index c89ac3ce..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/The_First_Time_I_Ever_Played_ROBLOX.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d0f0653e895011cd850afb99be03de084838070e904441859c23c36f4f5b9abf -size 90707 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/The_Friendly_Eviscerator_22500129.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/The_Friendly_Eviscerator_22500129.png new file mode 100644 index 00000000..d71477e8 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/The_Friendly_Eviscerator_22500129.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4235351005b57b8be823c1035dd89116871c0a6aed3e6ba7d5c3ff92e1ac6184 +size 64142 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/The_Winning_Smile_616380929.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/The_Winning_Smile_616380929.png new file mode 100644 index 00000000..e92ea9af --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/The_Winning_Smile_616380929.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2411ef6ca7c37d44de87ba0aba9b471d504841523879d6e2cb50f540f804d10c +size 64005 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Thinking_29716262.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Thinking_29716262.png new file mode 100644 index 00000000..cea88200 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Thinking_29716262.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cece87408b73777dad8204d4dafee50c069772f890d068fc4e2f2f35ee74dfa8 +size 60198 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Three_One_15177601.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Three_One_15177601.png new file mode 100644 index 00000000..80863777 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Three_One_15177601.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dbb5429c66bdbbe7efd437949c38366923bb06572515e0fe9b502443d70d51ca +size 56743 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Tiger_Chase_Fear_Face_258198928.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Tiger_Chase_Fear_Face_258198928.png new file mode 100644 index 00000000..6630a7f0 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Tiger_Chase_Fear_Face_258198928.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:052372d9cc79e35cc748205052f2b039b30d55bf64bc24f1f3ee7b6cdaca0de4 +size 60996 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Tired_Face_141728790.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Tired_Face_141728790.png new file mode 100644 index 00000000..76c705a7 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Tired_Face_141728790.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a00cf95ce11719fb703da0ab392799140935a00436b4aa1c9ad3f9561c9a791e +size 47572 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Tohru_The_Phantom_Claws_Face_1384270693.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Tohru_The_Phantom_Claws_Face_1384270693.png new file mode 100644 index 00000000..66f2b3e7 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Tohru_The_Phantom_Claws_Face_1384270693.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a4ab4ea2b49cbe7e01573dbe0bb710a0a2cb61a5e7a54727832bd9bb1e2f1002 +size 58298 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Too_Much_Candy_295763789.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Too_Much_Candy_295763789.png new file mode 100644 index 00000000..ad9bcc97 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Too_Much_Candy_295763789.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c7a1390fca7922fcf6cd2e683a34d3f7f35f2f63fa1c815e344b21dc7e2072b2 +size 60940 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Toothless_19399752.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Toothless_19399752.png new file mode 100644 index 00000000..fcdfcae0 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Toothless_19399752.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d2dca1417641a50148869c5e9ff0213c01a5612e8013d1bc2228fc42a6bffa8b +size 62370 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Toothy_Grin_7075434.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Toothy_Grin_7075434.png new file mode 100644 index 00000000..da2b3468 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Toothy_Grin_7075434.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:744169183d684ac0eed1ab27e8187aad1818526279e3004a308b49bf8b0b694e +size 49303 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Torque_The_Blue_Orc_2830496106.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Torque_The_Blue_Orc_2830496106.png new file mode 100644 index 00000000..2e2f7ecb --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Torque_The_Blue_Orc_2830496106.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f2657a516ec01a8adfcba6714d9730735d9572c9c5a1a9bb3de366f10615ae7 +size 94296 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Torque_The_Green_Orc_2830497827.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Torque_The_Green_Orc_2830497827.png new file mode 100644 index 00000000..c632aaa4 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Torque_The_Green_Orc_2830497827.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:02c896d4280f5dac95d4126a5cd2c5a718a095a8813e6b384ea1aa2d7f1f7928 +size 98306 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Torque_the_Green_Orc.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Torque_the_Green_Orc.png deleted file mode 100644 index a7935eca..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Torque_the_Green_Orc.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7fa43ec20348f333c9faf04a9d063530d151d8ca9e4075981556676fc2c092d9 -size 140818 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Trance.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Trance.png deleted file mode 100644 index 08a82e0e..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Trance.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3bbd69421260e2be5365f23e747c709926290f94bc2d96e0ae578aec373e91b9 -size 96938 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Troublemaker.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Troublemaker.png deleted file mode 100644 index d593ee45..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Troublemaker.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e34873aa461e700a0fb23ca68f96bc4f9438a788a8d6d081098f09b872a1efde -size 102188 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Uh_Oh_7074944.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Uh_Oh_7074944.png new file mode 100644 index 00000000..8b48460b --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Uh_Oh_7074944.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f199ab283f6687bec3abb35ba36589a7b2b4a2bcf58a4608c85cef9200286669 +size 46987 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Up_To_Something_1016186364.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Up_To_Something_1016186364.png new file mode 100644 index 00000000..2970aa3f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Up_To_Something_1016186364.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a1db578071a109e3c321a291ec16e31eb2162620d31b9b52816019f650e0dfb +size 53220 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Vampire_29532363.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Vampire_29532363.png new file mode 100644 index 00000000..04e632ca --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Vampire_29532363.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1bdac71f32abc3379943e0f9c5f180155a1f3de5811b5a8eff763d653cb174f +size 62293 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Vans_Checkerboard_Blue_Eyes_8247356154.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Vans_Checkerboard_Blue_Eyes_8247356154.png new file mode 100644 index 00000000..3d124b24 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Vans_Checkerboard_Blue_Eyes_8247356154.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3338965e43b1d456963c4de7c4093c8a6016795cf69d529ab3d90b1c37ef1e01 +size 100732 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Violet_Fang_362051899.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Violet_Fang_362051899.png new file mode 100644 index 00000000..facc0179 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Violet_Fang_362051899.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:76b0edd3067ce16343fe588416b22b489052da5c61c4bd4760400d3c4a233cd9 +size 60482 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Violet_Starry_Sight_2222775930.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Violet_Starry_Sight_2222775930.png new file mode 100644 index 00000000..e53fe884 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Violet_Starry_Sight_2222775930.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d4aa690dc221dc7cb71a000b65439c06c70110cfc5bf5854cafe57cb299eb8a2 +size 65492 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Visual_Studio_Seized_Up_For45_Seconds_Again_14083380.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Visual_Studio_Seized_Up_For45_Seconds_Again_14083380.png new file mode 100644 index 00000000..0749183c --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Visual_Studio_Seized_Up_For45_Seconds_Again_14083380.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:848670d067c62b266ece243e1c037d95e530b29ebd034e2259f30bcf6ab57634 +size 49315 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Walk_The_Plank_You_Scurvy_Dogs_13478124.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Walk_The_Plank_You_Scurvy_Dogs_13478124.png new file mode 100644 index 00000000..b99e390e --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Walk_The_Plank_You_Scurvy_Dogs_13478124.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b552829457963a1acd5e60da8da9dde86d3ab9588681e79f0a7de4a148d189db +size 58811 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Whaaaaaa_14127194.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Whaaaaaa_14127194.png new file mode 100644 index 00000000..3d5d9747 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Whaaaaaa_14127194.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cd32a5bfba6e4124e3d358ab36406eb08821d5ec26c904433fefa0aa6758a57c +size 60213 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Whistle_22877700.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Whistle_22877700.png new file mode 100644 index 00000000..3d8d4dff --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Whistle_22877700.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:385dbd2646e53363a58838ec0674eff7a3b00ed02a7956485d13ee4273e27b1f +size 47740 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Winkblink_22828351.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Winkblink_22828351.png new file mode 100644 index 00000000..cda104dc --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Winkblink_22828351.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac7f52b242c059a1bd3e5f7a197b26d983c8d028874802375f69c21611207f10 +size 52236 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Winky_7074864.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Winky_7074864.png new file mode 100644 index 00000000..4643764d --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Winky_7074864.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:980ec74cb51165ff09638aef98ceb6a3e0842f4ae89178a99df7018f8d5c0a42 +size 47172 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Winning_Smile_880469676.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Winning_Smile_880469676.png new file mode 100644 index 00000000..d64ba33c --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Winning_Smile_880469676.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1c8f5287685a62936d16a07e195a6e8290cb3c15fff65f06241974beca2bc99b +size 60427 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Woman_Face_86487766.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Woman_Face_86487766.png new file mode 100644 index 00000000..29832188 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Woman_Face_86487766.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ce1a288a7fbd627f741f71ae8374c2196bfcf7acff6ba457ba4a3e103c791d6 +size 74158 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Wonder_Womans_Golden_Armor_Face_6029816756.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Wonder_Womans_Golden_Armor_Face_6029816756.png new file mode 100644 index 00000000..11e5c2f6 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Wonder_Womans_Golden_Armor_Face_6029816756.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2b609290fd7c369ede2a598acbfef04082bed1f6770cf8d0e1933b64c69ab84f +size 60325 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Xd20_406001052.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Xd20_406001052.png new file mode 100644 index 00000000..50d3571f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Xd20_406001052.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7c2e3e91c73bed184ddca0f9f63b1ba95cff109de7c5b7afbea93d849c8c99fc +size 54314 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Xd_15054426.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Xd_15054426.png new file mode 100644 index 00000000..3a778c12 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Xd_15054426.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd5bc0cae12bed1adf598ed3120ec43f74ad44ccf0fbff15af92b4d2d4f308ad +size 54614 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Xtreme_Happy_20644021.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Xtreme_Happy_20644021.png new file mode 100644 index 00000000..e0ee754f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Xtreme_Happy_20644021.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b89e5359adaeea0c26d1e919f87ba3f1aa5bccf348e31a6a10cb7b6a431acdcc +size 75333 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Yaaawwn_162068415.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Yaaawwn_162068415.png new file mode 100644 index 00000000..110b499d --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Yaaawwn_162068415.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f1e029329b3c68542b56fc22bb9f334a94923063c7cb12e951519ce1e7ae9098 +size 50037 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Yawn_20010377.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Yawn_20010377.png new file mode 100644 index 00000000..6a56d037 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Yawn_20010377.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9fbfc25adefd3c30f2557eb3f89c8fd01454368ba51dcd895b6d644df3dd9ec2 +size 51716 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Yellow_Starface_162200696.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Yellow_Starface_162200696.png new file mode 100644 index 00000000..309b0ab1 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Yellow_Starface_162200696.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e5517c3c1699e97534e91e448cca768a7d0d7be7e09bc81bab7e4f96fb699a2 +size 67002 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/You_Ated_My_Caik_21635583.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/You_Ated_My_Caik_21635583.png new file mode 100644 index 00000000..10c571db --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/You_Ated_My_Caik_21635583.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa0037a5396a918e3bd3d01fa67306a39d5434c948a77cc2789ad53c6e396253 +size 53803 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Zoey_Face_807339121.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Zoey_Face_807339121.png new file mode 100644 index 00000000..0ccfe09e --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Zoey_Face_807339121.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:555ad328d2c2059ee295c4fcdb9ce3a7d57c09a53dfd4c3fbc3b2ba5ac9f2160 +size 56751 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Zombie_Face_133360789.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Zombie_Face_133360789.png new file mode 100644 index 00000000..18fe8322 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/Zombie_Face_133360789.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ecfaeda72db89a4a4ed03ae3a8f2c77834f0daac9b7164450e16ce2406337dac +size 114253 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/dollar-dot-dollar.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/dollar-dot-dollar.png deleted file mode 100644 index 71f7c692..00000000 --- a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/dollar-dot-dollar.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dcc8580b9438382a32be76e7fdf1c06f45ea46d4fea238089d4aaf1e9a031b1d -size 77981 diff --git a/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/love_11611321.png b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/love_11611321.png new file mode 100644 index 00000000..88a8009d --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/art/avatar/classic-head/love_11611321.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0067f0469272542524191752d20c923a1be53b1efaad7dc8e19bb30de9b52feb +size 52630 diff --git a/.cursor/rules/roblox/en-us/assets/feeds/ads_manager.webp b/.cursor/rules/roblox/en-us/assets/feeds/ads_manager.webp new file mode 100644 index 00000000..42e404d3 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/feeds/ads_manager.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:905e17385e0f2601e934ebcad248b05e6280786c6638c774ff4b6bf52f4b30c1 +size 104916 diff --git a/.cursor/rules/roblox/en-us/assets/feeds/age-based-chat.webp b/.cursor/rules/roblox/en-us/assets/feeds/age-based-chat.webp index 030b45fd..254bde46 100644 --- a/.cursor/rules/roblox/en-us/assets/feeds/age-based-chat.webp +++ b/.cursor/rules/roblox/en-us/assets/feeds/age-based-chat.webp @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8263a237050e69a138026ee0b98b1e7264770f071531d6c85de219d6a3e156fa -size 30692 +oid sha256:185a8abf0f74a77ad5dcb67338a85f2c21cde2015131139f2134b6f32fe1cfa9 +size 95956 diff --git a/.cursor/rules/roblox/en-us/assets/feeds/age_chat.webp b/.cursor/rules/roblox/en-us/assets/feeds/age_chat.webp index 3ad00a3b..254bde46 100644 --- a/.cursor/rules/roblox/en-us/assets/feeds/age_chat.webp +++ b/.cursor/rules/roblox/en-us/assets/feeds/age_chat.webp @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4c0ad978ad4eb85f5a9ec2d81de8c817f0f82e4abe52ff12c0b82535011fb2b0 -size 94002 +oid sha256:185a8abf0f74a77ad5dcb67338a85f2c21cde2015131139f2134b6f32fe1cfa9 +size 95956 diff --git a/.cursor/rules/roblox/en-us/assets/modeling/model-generation/Behaviors.rbxm b/.cursor/rules/roblox/en-us/assets/modeling/model-generation/Behaviors.rbxm new file mode 100644 index 00000000..e45630ed --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/modeling/model-generation/Behaviors.rbxm @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cd462c906657998f7a9f1f8181d6517171c010f9979b0b992fcc1c049b26569e +size 154422 diff --git a/.cursor/rules/roblox/en-us/assets/modeling/model-generation/Green-Dragon-Car-Driving.mp4 b/.cursor/rules/roblox/en-us/assets/modeling/model-generation/Green-Dragon-Car-Driving.mp4 new file mode 100644 index 00000000..36bc286d --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/modeling/model-generation/Green-Dragon-Car-Driving.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21340c6ab106501a1e8503cbe110e279be714826ebac4413e9341e1c8672d018 +size 9624930 diff --git a/.cursor/rules/roblox/en-us/assets/modeling/model-generation/Green-Dragon-Car.jpg b/.cursor/rules/roblox/en-us/assets/modeling/model-generation/Green-Dragon-Car.jpg new file mode 100644 index 00000000..ca25a10e --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/modeling/model-generation/Green-Dragon-Car.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e053efda2a6ff818419a06677eb6117bdc0728e615fa38b1200d6cd0187118b6 +size 259343 diff --git a/.cursor/rules/roblox/en-us/assets/players/teleport-access-control.png b/.cursor/rules/roblox/en-us/assets/players/teleport-access-control.png new file mode 100644 index 00000000..c700ab22 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/players/teleport-access-control.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0350827c07a2f93e51d30447e9ab244bac092d966aabd193cfcee421c18c3c31 +size 52376 diff --git a/.cursor/rules/roblox/en-us/assets/promotion/ads-manager/AdsManagerMetricCards.png b/.cursor/rules/roblox/en-us/assets/promotion/ads-manager/AdsManagerMetricCards.png new file mode 100644 index 00000000..b9490a08 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/promotion/ads-manager/AdsManagerMetricCards.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:50e93e4560b50cfd3893b0f83c97f4e345a94f61edcd16c4a099a3802cf72d4a +size 51111 diff --git a/.cursor/rules/roblox/en-us/assets/promotion/ads-manager/AdsManagerReporting.png b/.cursor/rules/roblox/en-us/assets/promotion/ads-manager/AdsManagerReporting.png new file mode 100644 index 00000000..da2607e8 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/promotion/ads-manager/AdsManagerReporting.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9988e31afb61e5917f898d822eaf0ebfa351c27bbf6b1e1c7068934611cdbf81 +size 264422 diff --git a/.cursor/rules/roblox/en-us/assets/promotion/ads-manager/AdsManagerReportingTable.png b/.cursor/rules/roblox/en-us/assets/promotion/ads-manager/AdsManagerReportingTable.png new file mode 100644 index 00000000..8014a14f --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/promotion/ads-manager/AdsManagerReportingTable.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9783a81f75dc1a62fb5ce5169a20ece6b6be37578603f35556f58c9eb830e08b +size 275221 diff --git a/.cursor/rules/roblox/en-us/assets/promotion/ads-manager/AdsOverview.png b/.cursor/rules/roblox/en-us/assets/promotion/ads-manager/AdsOverview.png new file mode 100644 index 00000000..cbf56636 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/promotion/ads-manager/AdsOverview.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:514e6f9fdef03931af11523b1ed0718009f8d77d1032fff344922614a2ea2ba0 +size 60039 diff --git a/.cursor/rules/roblox/en-us/assets/studio/explorer/Model-Generation-Behaviors.png b/.cursor/rules/roblox/en-us/assets/studio/explorer/Model-Generation-Behaviors.png new file mode 100644 index 00000000..146a42f5 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/studio/explorer/Model-Generation-Behaviors.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8972f90d066fcdb43b2905636f411823e17cd0ea4fe2a74cce7adcbe243badf3 +size 24303 diff --git a/.cursor/rules/roblox/en-us/assets/studio/explorer/Model-Generation-Hierarchy.png b/.cursor/rules/roblox/en-us/assets/studio/explorer/Model-Generation-Hierarchy.png new file mode 100644 index 00000000..8ab420c2 --- /dev/null +++ b/.cursor/rules/roblox/en-us/assets/studio/explorer/Model-Generation-Hierarchy.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a4c238c444bcfdbb044dfee038441ef104f7b948076071c85769030a741c66ac +size 54863 diff --git a/.cursor/rules/roblox/en-us/assistant/guide.md b/.cursor/rules/roblox/en-us/assistant/guide.md index fecc706e..a1fb6c2a 100644 --- a/.cursor/rules/roblox/en-us/assistant/guide.md +++ b/.cursor/rules/roblox/en-us/assistant/guide.md @@ -20,7 +20,7 @@ In Studio, Assistant consists of a large language model (LLM) that generates cod For a more in-depth look at what Assistant can do and how to use it, see the [Prompt guide and examples](prompt-engineering.md) and the following Roblox Staff livestream for tips, tricks, and inspiration. - + ### Insert and modify scripts diff --git a/.cursor/rules/roblox/en-us/avatar-setup/auto-setup.md b/.cursor/rules/roblox/en-us/avatar-setup/auto-setup.md index cfa489ab..a506f35c 100644 --- a/.cursor/rules/roblox/en-us/avatar-setup/auto-setup.md +++ b/.cursor/rules/roblox/en-us/avatar-setup/auto-setup.md @@ -7,7 +7,7 @@ description: The Avatar setup tool previews animations, clothing, accessories, a Auto-setup is currently in [active development](https://devforum.roblox.com/t/avatar-auto-setup-now-supports-clothing-and-accessories/3709128) with many improvements on the roadmap. Note that some inputs might work better than others and your results can vary over time as additional training and improvements are made. -
+
If [Avatar Setup](./index.md) detects that the input model is an incomplete avatar asset model, the **auto-setup** feature attempts to convert the model into an avatar asset with all the advanced components that allow characters to interact with the world and express themselves with accessories and clothing.
diff --git a/.cursor/rules/roblox/en-us/avatar-setup/tools.md b/.cursor/rules/roblox/en-us/avatar-setup/tools.md index 0a9390cf..971d1312 100644 --- a/.cursor/rules/roblox/en-us/avatar-setup/tools.md +++ b/.cursor/rules/roblox/en-us/avatar-setup/tools.md @@ -74,7 +74,7 @@ As **Avatar Setup** continues development, check here for additional tools and f ### Edit cage meshes - +

You can modify your body cage mesh using the cage mesh editing tool. Use the brush and various brush settings to modify your cage, allowing you to make adjustments to how clothing and other layered assets fit on your character.
diff --git a/.cursor/rules/roblox/en-us/avatar/index.md b/.cursor/rules/roblox/en-us/avatar/index.md index 4f9d0419..4ae9e316 100644 --- a/.cursor/rules/roblox/en-us/avatar/index.md +++ b/.cursor/rules/roblox/en-us/avatar/index.md @@ -250,7 +250,7 @@ title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" -allowfullscreen > +allowFullScreen > )}

{content.title}

diff --git a/.cursor/rules/roblox/en-us/education/developer/designing-educational-experiences.md b/.cursor/rules/roblox/en-us/education/developer/designing-educational-experiences.md index a541126a..7d98ad64 100644 --- a/.cursor/rules/roblox/en-us/education/developer/designing-educational-experiences.md +++ b/.cursor/rules/roblox/en-us/education/developer/designing-educational-experiences.md @@ -32,4 +32,4 @@ Download the presentation as a `.PDF` below. The below presentation was taken at Connect 2022, a virtual conference focused on game development in Roblox. - + diff --git a/.cursor/rules/roblox/en-us/experiences.md b/.cursor/rules/roblox/en-us/experiences.md index 2aecfb9b..f9bc6da1 100644 --- a/.cursor/rules/roblox/en-us/experiences.md +++ b/.cursor/rules/roblox/en-us/experiences.md @@ -128,7 +128,7 @@ that teaches you the skills you need to create and monetize your experiences.
- +
Environmental art Environmental Art teaches you how to create a high-quality environment for a laser tag experience. @@ -146,7 +146,7 @@ that teaches you the skills you need to create and monetize your experiences.
- +
Gameplay scripting Gameplay Scripting teaches you how to organize and implement the scripting logic for large, complex project. @@ -164,7 +164,7 @@ that teaches you the skills you need to create and monetize your experiences.
- +
UI Design UI Design teaches you how to plan and implement UI components for unique user flows. diff --git a/.cursor/rules/roblox/en-us/get-started.md b/.cursor/rules/roblox/en-us/get-started.md index 5bc8d74b..ec2f46c5 100644 --- a/.cursor/rules/roblox/en-us/get-started.md +++ b/.cursor/rules/roblox/en-us/get-started.md @@ -170,7 +170,7 @@ export const sections = [ frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" - allowfullscreen + allowFullScreen > )}

{content.title}

diff --git a/.cursor/rules/roblox/en-us/luau/native-code-gen.md b/.cursor/rules/roblox/en-us/luau/native-code-gen.md index b364f14c..bb4a4628 100644 --- a/.cursor/rules/roblox/en-us/luau/native-code-gen.md +++ b/.cursor/rules/roblox/en-us/luau/native-code-gen.md @@ -5,7 +5,7 @@ description: Luau Native Code Generation allows Luau code to be translated direc With Luau support for native code generation, server-side scripts in your experience can be compiled directly into the machine code instructions that CPUs execute, rather than regular bytecode that the Luau VM operates on. This feature can be used to improve execution speed for some scripts on the server, in particular those that have a lot of numerical computation without using too many heavy Luau library or Roblox API calls. - + ## Enable native code generation diff --git a/.cursor/rules/roblox/en-us/makeup/import.md b/.cursor/rules/roblox/en-us/makeup/import.md index 781546b5..164371e9 100644 --- a/.cursor/rules/roblox/en-us/makeup/import.md +++ b/.cursor/rules/roblox/en-us/makeup/import.md @@ -41,7 +41,7 @@ These instructions apply specifically to the Makeup test place, available in the ## Test with Avatar Setup - +
You can also use the Avatar Setup tool to preview makeup assets without playtesting. diff --git a/.cursor/rules/roblox/en-us/makeup/index.md b/.cursor/rules/roblox/en-us/makeup/index.md index 9a17ff85..629d347d 100644 --- a/.cursor/rules/roblox/en-us/makeup/index.md +++ b/.cursor/rules/roblox/en-us/makeup/index.md @@ -232,3 +232,38 @@ A comprehensive `.zip` folder of `.fbx` and `.gltf` assets, including multiple r
+ +### Reference experience + + + + + +
Reference place file (download)
+
+
+ +
+
+
+ At this time, you can only test makeup on the downloadable placefile. +
+ In Github, select the download icon on the right-side to download the 'MakeupBeta.zip'. +
+
+ + + +
+
+ +
diff --git a/.cursor/rules/roblox/en-us/makeup/reassign-textures.md b/.cursor/rules/roblox/en-us/makeup/reassign-textures.md index d9bde2c5..0737355e 100644 --- a/.cursor/rules/roblox/en-us/makeup/reassign-textures.md +++ b/.cursor/rules/roblox/en-us/makeup/reassign-textures.md @@ -22,7 +22,7 @@ The following are video workflows for various tasks in exporting textures from a Reassigning textures in Blender -

+

Additional notes: @@ -37,7 +37,7 @@ Additional notes: Reassigning textures in Maya - + @@ -47,7 +47,7 @@ Additional notes: Exporting textures from Photoshop -

+

Additional notes: @@ -61,7 +61,7 @@ Additional notes: Exporting textures from Substance Painter - + diff --git a/.cursor/rules/roblox/en-us/marketplace/homestore.md b/.cursor/rules/roblox/en-us/marketplace/homestore.md index 59c6d4dd..74b5d14c 100644 --- a/.cursor/rules/roblox/en-us/marketplace/homestore.md +++ b/.cursor/rules/roblox/en-us/marketplace/homestore.md @@ -3,7 +3,7 @@ title: UGC Homestore description: Showcase and sell your published avatar items in a easily customizable shop template. --- -
+
The **UGC Homestore** is a user-friendly template that avatar item creators can use to showcase and sell their marketplace items. This template is ideal for creators with an existing UGC catalog who want a dedicated space to promote their assets. Creators who sell their own avatar items from their own experience also benefit from a [larger commission split](../marketplace/marketplace-fees-and-commissions.md#commissions). diff --git a/.cursor/rules/roblox/en-us/marketplace/publish-to-marketplace.md b/.cursor/rules/roblox/en-us/marketplace/publish-to-marketplace.md index edf3ff52..507af671 100644 --- a/.cursor/rules/roblox/en-us/marketplace/publish-to-marketplace.md +++ b/.cursor/rules/roblox/en-us/marketplace/publish-to-marketplace.md @@ -3,7 +3,7 @@ title: Publish to Marketplace description: Explains how to publish user-generated content to the Marketplace. --- - +

In order to publish and sell assets on the Marketplace, your account or group must first meet [Roblox's Creator and Group requirements](../marketplace/marketplace-policy.md#creator-and-group-requirements). Users who satisfy the requirements and have not hit their [publishing limits](#upload-and-publish-limits), can upload and sell their assets in the following general steps: diff --git a/.cursor/rules/roblox/en-us/matchmaking/index.md b/.cursor/rules/roblox/en-us/matchmaking/index.md index a77db8de..c2c63c00 100644 --- a/.cursor/rules/roblox/en-us/matchmaking/index.md +++ b/.cursor/rules/roblox/en-us/matchmaking/index.md @@ -5,7 +5,7 @@ description: Match players to servers inside your experience. Matchmaking is the process of matching players to servers based on player characteristics like age, language, skill level, and other gameplay preferences. - + ## How matchmaking works diff --git a/.cursor/rules/roblox/en-us/parts/model-generation.md b/.cursor/rules/roblox/en-us/parts/model-generation.md new file mode 100644 index 00000000..77353e18 --- /dev/null +++ b/.cursor/rules/roblox/en-us/parts/model-generation.md @@ -0,0 +1,247 @@ +--- +title: Model generation +description: How text prompts and preset schemas can generate both static 3D assets and fully functional models such as vehicles that drive, planes that fly, and weapons that shoot. +--- + +Through text prompts and preset schemas, you (and players in‑experience) can generate both static 3D assets and **fully functional** models such as vehicles that drive, planes that fly, and weapons that shoot. This guide demonstrates how to use `Class.GenerationService:GenerateModelAsync()|GenerateModelAsync()` as part of a dynamic, player‑driven creative experience. + +## Overview + +`Class.GenerationService:GenerateModelAsync()|GenerateModelAsync()` enables generation of multi‑mesh geometries with the following advantages: + +- The provided [schema](#schema-based-generation) defines how the generated geometry will be broken into parts. +- Any object generated in-experience will be replicated and visible to all players, allowing them to build together in real‑time. +- Generated meshes are higher fidelity with better overall forms, silhouettes, more detail, and fewer artifacts. Generated textures are more coherent and detailed, with less graininess and less pronounced baked‑in lighting. +- Generation times have lower latency, enabling quicker and more responsive creation in experiences. +- You and even players during gametime can specify bounding boxes to suggest size and proportions of the generated model. +- An optional max triangle count keeps generated objects performant for your experience. + +## Schema-based generation + +To create articulated, functional objects, the generated geometry must be separated into multiple `Class.MeshPart|MeshParts`. For example, to create a drivable car with wheels that spin and steer, at least five `Class.MeshPart|MeshParts` are needed: one for the car body and four for each of the car's wheels. `Class.GenerationService:GenerateModelAsync()|GenerateModelAsync()` achieves this through a preset **schema** as shown in the following code snippet: + +```lua title="Script in ServerScriptService" +local GenerationService = game:GetService("GenerationService") +local Workspace = game:GetService("Workspace") + +-- Set up inputs for the generated geometry +local inputs = { + TextPrompt = "green dragon car with 4 wheels" +} +-- Set schema to the predefined five-model car chassis +local schema = { + PredefinedSchema = "Car5" +} + +-- Make the call to generate the model +local success, result, metadata = pcall(function() + return GenerationService:GenerateModelAsync(inputs, schema) +end) +if success then + -- Scale model to target size and position near world center + local targetSize = 16 + local modelSize = result:GetExtentsSize() + local scaleFactor = targetSize / math.max(modelSize.X, modelSize.Y, modelSize.Z) + result:ScaleTo(scaleFactor) + result:PivotTo(CFrame.new(0, result:GetExtentsSize().Y / 2, -40)) + + -- Anchor all parts so that the meshes don't fall apart + for _, descendant in result:GetDescendants() do + if descendant:IsA("BasePart") then + descendant.Anchored = true + end + end + + -- Name the model and parent it to workspace + result.Name = "BasicDragonCarGeneration" + result.Parent = Workspace +else + warn(result) +end +``` + + +`Class.GenerationService:GenerateModelAsync()|GenerateModelAsync()` currently supports two fixed schemas: `Car5` which produces a car with a body and four wheels, and `Body1` which yields a single `Class.MeshPart` object. Additional schemas will be supported in the future, as well as creator‑customized (open) schemas. + + +The following image shows the expected output and its construction as it appears in the [Explorer](../studio/explorer.md) hierarchy: + + + + + + + + + + +## Retargetable scripts + +In Roblox, **behaviors** typically encompass the scripts, attachments, [constraints](../physics/index.md#constraints), and other instance types attached to static textured geometries to make them functional. Since `Class.GenerationService:GenerateModelAsync()|GenerateModelAsync()` generates a wide range of geometries on‑the‑fly, **retargetable scripts** must be attached to automatically adapt behaviors to expected functionality. + +For example, consider an experience where players get to make their own drivable cars. `Class.GenerationService:GenerateModelAsync()|GenerateModelAsync()` takes the player prompt and generates five distinct meshes (body and four wheels) via the `Car5` [schema](#schema-based-generation). Then, a preset retargetable script adapts its driving behavior to the size and shape of the model to ensure the car is drivable and its wheels spin realistically. + +```mermaid +block-beta +columns 1 + + block:Main + columns 5 + Prompt(["   prompt   
   (creator)   "]) + Generate{" Geometry 
 Generator 
(Roblox)"} + + Geometry(("GEOMETRY
   single / multi-mesh   ")) + space:2 + Schema(["   schema   "]) + space + Retarget{"    Retarget    
behavior
(creator)"} + space + FunctionalModel((("    FUNCTIONAL    
MODEL"))) + + Prompt --> Generate + Generate --> Geometry + Geometry --> Retarget + Retarget --> FunctionalModel + Schema --> Generate +end + +style Main fill-opacity: 0, stroke-opacity: 0; +style Prompt color:white, fill:RoyalBlue; +style Schema color:white, fill:RoyalBlue; +style Generate color:white, fill:#9933FF, fill-opacity:0.7; +style Retarget color:white, fill:RoyalBlue; +style Geometry color:white, fill:SeaGreen +style FunctionalModel color:white, fill:SeaGreen +``` + +To test retargetable scripts: + +1. Download the `Behaviors.rbxm` file (right‑click and "save as" to your local system). +2. In Studio's [Explorer](../studio/explorer.md) hierarchy, right‑click `Class.ReplicatedStorage`, select **Insert** ⟩ **Import Roblox Model**, and choose the downloaded file. The model unpacks into several folders. + + + +3. Copy and paste one of the following code snippets into a server `Class.Script` within `Class.ServerScriptService`, depending on the object type you'd like to generate. + + + + This example generates a functional car with a brake, nitro boost, audio and visual effects, and an on‑screen UI speedometer. + + ```lua title="Script in ServerScriptService" + local GenerationService = game:GetService("GenerationService") + local ReplicatedStorage = game:GetService("ReplicatedStorage") + local Workspace = game:GetService("Workspace") + + -- Set up inputs for the generated geometry + local inputs = { + TextPrompt = "green dragon car with 4 wheels" + } + -- Set schema to the predefined five-model car chassis + local schema = { + PredefinedSchema = "Car5" + } + + -- Make the call to generate the model + local success, result, metadata = pcall(function() + return GenerationService:GenerateModelAsync(inputs, schema) + end) + if success then + -- Scale model to target size + local targetSize = 16 + local modelSize = result:GetExtentsSize() + local scaleFactor = targetSize / math.max(modelSize.X, modelSize.Y, modelSize.Z) + result:ScaleTo(scaleFactor) + + -- Load "makeFunctional" module for "CarBehavior" + local makeFunctional = require(ReplicatedStorage.Behaviors.CarBehavior.makeFunctional) + + -- Reference car parts by names guaranteed through the "Car5" schema + local body = result:FindFirstChild("body") + local frontLeftWheel = result:FindFirstChild("front left wheel") + local frontRightWheel = result:FindFirstChild("front right wheel") + local rearLeftWheel = result:FindFirstChild("rear left wheel") + local rearRightWheel = result:FindFirstChild("rear right wheel") + + -- Set behavioral configuration parameters + local config = { + seatPosition = "inside", + invisibleWhenSeated = false + } + + -- Attach behavior via the "makeFunctional" script + local functionalModel = makeFunctional(result, frontLeftWheel, frontRightWheel, rearLeftWheel, rearRightWheel, body, config) + + -- Position the model near world center + functionalModel:PivotTo(CFrame.new(0, functionalModel:GetExtentsSize().Y / 2, -40)) + functionalModel.Name = "BasicDragonCarGeneration" + functionalModel.Parent = Workspace + else + warn(result) + end + ``` + + + + + To test other generated models with retargetable scripts in the `Car5` schema, change the `TextPrompt` string value on line 7 and playtest again. Ideas include: + + - `"yellow sports car with a spoiler"` + - `"purple bat car with 4 wheels"` + - `"giant monster truck with spiked roof"` + + + + + This example generates a basic plane using the `Body1` schema that flies through player input. + + ```lua title="Script in ServerScriptService" + local GenerationService = game:GetService("GenerationService") + local ReplicatedStorage = game:GetService("ReplicatedStorage") + local Workspace = game:GetService("Workspace") + + -- Set up inputs for the generated geometry + local inputs = { + TextPrompt = "basic paper airplane with two wings" + } + -- Set schema to the predefined static body + local schema = { + PredefinedSchema = "Body1" + } + + -- Make the call to generate the model + local success, result, metadata = pcall(function() + return GenerationService:GenerateModelAsync(inputs, schema) + end) + if success then + -- Scale model to target size + local targetSize = 30 + local modelSize = result:GetExtentsSize() + local scaleFactor = targetSize / math.max(modelSize.X, modelSize.Y, modelSize.Z) + result:ScaleTo(scaleFactor) + + -- Load "makeFunctional" module for "AirplaneBehavior" + local makeFunctional = require(ReplicatedStorage.Behaviors.AirplaneBehavior.makeFunctional) + + -- Set behavioral configuration parameters + local config = { + seatPosition = "ontop", + forwardSpeed = 80, + turnSpeed = 8 + } + + -- Attach behavior via the "makeFunctional" script + local functionalModel = makeFunctional(result, config) + + -- Place model slightly above ground to let it fall into place + local boundingBox = functionalModel:GetBoundingBox() + local location = Vector3.new(0, boundingBox.Y / 2 + 3, -40) + functionalModel:PivotTo(CFrame.new(location)) + functionalModel.Name = "BasicPlaneGeneration" + functionalModel.Parent = Workspace + else + warn(result) + end + ``` + + + diff --git a/.cursor/rules/roblox/en-us/platform.md b/.cursor/rules/roblox/en-us/platform.md index b1c2f159..9b574d09 100644 --- a/.cursor/rules/roblox/en-us/platform.md +++ b/.cursor/rules/roblox/en-us/platform.md @@ -237,7 +237,7 @@ title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" -allowfullscreen > +allowFullScreen > )}

{content.title}

{content.description}

diff --git a/.cursor/rules/roblox/en-us/production/analytics/acquisition.md b/.cursor/rules/roblox/en-us/production/analytics/acquisition.md index 8aeb973e..1841ca1e 100644 --- a/.cursor/rules/roblox/en-us/production/analytics/acquisition.md +++ b/.cursor/rules/roblox/en-us/production/analytics/acquisition.md @@ -64,15 +64,15 @@ Here's a list of all the available acquisition sources: Sponsored ads - Acquisition from [sponsored experiences](../promotion/ads-manager.md#sponsored-experiences) and **Sponsored Takeovers** on **Home** + Acquisition from [sponsored experiences](../promotion/ads-manager.md) and **Sponsored Takeovers** on **Home** Search ads - Acquisition from [search ads](../promotion/search-ads.md) + Acquisition from [search ads](../promotion/ads-manager.md) Portal ads - Acquisition from [portal ads](../promotion/ads-manager.md#portal-ads) + Acquisition from [portal ads](../monetization/immersive-ads.md#portal-ads) Teleport diff --git a/.cursor/rules/roblox/en-us/production/analytics/engagement.md b/.cursor/rules/roblox/en-us/production/analytics/engagement.md index 8204770c..dbadcf6b 100644 --- a/.cursor/rules/roblox/en-us/production/analytics/engagement.md +++ b/.cursor/rules/roblox/en-us/production/analytics/engagement.md @@ -3,7 +3,7 @@ title: Engagement description: Explains how to improve engagement metrics for your experience. --- - +
@@ -32,7 +32,7 @@ Usually, the friction of joining and leaving an experience is very low on Roblox 3. **Remove unnecessary barriers to social interaction**: Many successful experiences on Roblox highlight socializing with connections and other users a core part of their design. Try to design your experience to support group play and social interaction where possible. - + ### Give users a reason to keep coming back diff --git a/.cursor/rules/roblox/en-us/production/analytics/event-types.md b/.cursor/rules/roblox/en-us/production/analytics/event-types.md index ed2e9114..3f7e2a95 100644 --- a/.cursor/rules/roblox/en-us/production/analytics/event-types.md +++ b/.cursor/rules/roblox/en-us/production/analytics/event-types.md @@ -3,7 +3,7 @@ title: Event types description: Overview of using event types to track user sources, sinks and milestones in your experience. --- -
+
Event types help you identify opportunities to grow and monetize your experience. They allow you to **integrate event tracking in your experience** and visualize your in-experience economy and player usage patterns on the Analytics dashboard diff --git a/.cursor/rules/roblox/en-us/production/analytics/monetization.md b/.cursor/rules/roblox/en-us/production/analytics/monetization.md index 85e5bdc7..469141d7 100644 --- a/.cursor/rules/roblox/en-us/production/analytics/monetization.md +++ b/.cursor/rules/roblox/en-us/production/analytics/monetization.md @@ -3,7 +3,7 @@ title: Monetization description: Explains how to improve monetization metrics for your experience. --- - +
@@ -50,7 +50,7 @@ Here are some high level tips for growing your revenue: Devote as much creativity and attention to your storefront as you do to the rest of the experience. Users would appreciate an easy-to-find shop that helps them learn more about the experience. - + ## Improve payer conversion rate @@ -62,7 +62,7 @@ To improve this metric: 2. **Consider welcome offers and discounts for first-time purchasers**: This can lower the barrier for new users to try out your paid content to see how fun it is. 3. **Analyze the purchase funnel and identify any issues**: Possible issues include unclear or confusing steps in the purchase flow or distractions that make it difficult for users to complete the process. - + ## Improve average revenue per paying user (ARPPU) diff --git a/.cursor/rules/roblox/en-us/production/analytics/retention.md b/.cursor/rules/roblox/en-us/production/analytics/retention.md index 6d6379f1..29904548 100644 --- a/.cursor/rules/roblox/en-us/production/analytics/retention.md +++ b/.cursor/rules/roblox/en-us/production/analytics/retention.md @@ -3,7 +3,7 @@ title: Retention description: Explains how to improve retention metrics for your experience. --- - +
@@ -80,7 +80,7 @@ The following example is one path to improve your core loop: 2. **Balance the challenge** of your core loop to avoid user frustration and boredom. 3. **Reward users** for completing your core loop with feedback, currency, items, and achievements. - +
@@ -108,7 +108,7 @@ You can also use analytics to improve your FTUE: Avoid a complex or time consuming FTUE, as you want to get users to the fun as quickly as possible, ideally in 5 minutes or less after entering your experience. - +
@@ -146,7 +146,7 @@ You can use analytics to improve your progression system: 3. **Fix the progression system**. If users level up too quickly or too slowly, evaluate the difficulties of your progression system's tasks and adjust them accordingly to make sure users spend the proper amount of time on each level. - + ## Improve day 30 retention diff --git a/.cursor/rules/roblox/en-us/production/experiments.md b/.cursor/rules/roblox/en-us/production/experiments.md index ae03d906..5d8dfe39 100644 --- a/.cursor/rules/roblox/en-us/production/experiments.md +++ b/.cursor/rules/roblox/en-us/production/experiments.md @@ -198,7 +198,7 @@ For convenience, the results page lets you replace the default config value with ## Best practices for experiments -
+
- **Use the minimum detectable effect (MDE)** to decide if your experiment is worth running. diff --git a/.cursor/rules/roblox/en-us/production/game-design/analytics-essentials.md b/.cursor/rules/roblox/en-us/production/game-design/analytics-essentials.md index 36b548e4..587f03d7 100644 --- a/.cursor/rules/roblox/en-us/production/game-design/analytics-essentials.md +++ b/.cursor/rules/roblox/en-us/production/game-design/analytics-essentials.md @@ -15,7 +15,7 @@ For an in-depth look at all the analytics features Roblox offers to help you imp ## Engagement metrics - +
@@ -33,7 +33,7 @@ For out-of-the-box functionality to create engagement rewards, see the [Engageme ## Retention metrics - +
@@ -47,7 +47,7 @@ Retention metrics determine if players are returning to your experience. Three o ## Monetization metrics - +
diff --git a/.cursor/rules/roblox/en-us/production/game-design/content-updates.md b/.cursor/rules/roblox/en-us/production/game-design/content-updates.md index 08c91f6e..6388728d 100644 --- a/.cursor/rules/roblox/en-us/production/game-design/content-updates.md +++ b/.cursor/rules/roblox/en-us/production/game-design/content-updates.md @@ -3,7 +3,7 @@ title: Content updates description: Content updates --- - +
diff --git a/.cursor/rules/roblox/en-us/production/game-design/core-loops.md b/.cursor/rules/roblox/en-us/production/game-design/core-loops.md index a8201ddc..b68f1894 100644 --- a/.cursor/rules/roblox/en-us/production/game-design/core-loops.md +++ b/.cursor/rules/roblox/en-us/production/game-design/core-loops.md @@ -3,7 +3,7 @@ title: Core loops description: Core Loops --- - +
diff --git a/.cursor/rules/roblox/en-us/production/game-design/index.md b/.cursor/rules/roblox/en-us/production/game-design/index.md index 5a150a17..6e9ae41a 100644 --- a/.cursor/rules/roblox/en-us/production/game-design/index.md +++ b/.cursor/rules/roblox/en-us/production/game-design/index.md @@ -3,7 +3,7 @@ title: Design experiences on Roblox description: Design experiences on Roblox --- - +
@@ -13,11 +13,11 @@ A designer's role is to create an engaging experience for players, retain those
- +
Sketch Series: Onboarding Techniques
- +
Sketch Series: Subscription Design
@@ -27,11 +27,11 @@ A designer's role is to create an engaging experience for players, retain those
- +
Sketch Series: Subscription Design
- +
Sketch Series: Retention Metrics
diff --git a/.cursor/rules/roblox/en-us/production/game-design/introduction-to-quest-design.md b/.cursor/rules/roblox/en-us/production/game-design/introduction-to-quest-design.md index fcc26529..29176266 100644 --- a/.cursor/rules/roblox/en-us/production/game-design/introduction-to-quest-design.md +++ b/.cursor/rules/roblox/en-us/production/game-design/introduction-to-quest-design.md @@ -4,7 +4,7 @@ description: Introduction to Quest Design, achievements, and dailies. ---
- +
Introduction to quests, achievements, and dailies
@@ -175,11 +175,11 @@ In [_Spellbound_](https://www.roblox.com/games/6468323505/), the player accepts For a more in-depth look at quests, watch these workshop videos. They include tips for designing, writing, and producing quests, as well as developing a spreadsheet to make quest development more efficient.
- +
Designing quests, achievements, and dailies
- +
Writing quests, achievements, and dailies
diff --git a/.cursor/rules/roblox/en-us/production/game-design/liveops-essentials.md b/.cursor/rules/roblox/en-us/production/game-design/liveops-essentials.md index 34314571..40d88d4e 100644 --- a/.cursor/rules/roblox/en-us/production/game-design/liveops-essentials.md +++ b/.cursor/rules/roblox/en-us/production/game-design/liveops-essentials.md @@ -3,7 +3,7 @@ title: LiveOps essentials description: LiveOps Essentials is an overview of what live ops are and how to think about designing them effectively. --- - +
diff --git a/.cursor/rules/roblox/en-us/production/game-design/monetization-foundations.md b/.cursor/rules/roblox/en-us/production/game-design/monetization-foundations.md index d549f52d..0d378799 100644 --- a/.cursor/rules/roblox/en-us/production/game-design/monetization-foundations.md +++ b/.cursor/rules/roblox/en-us/production/game-design/monetization-foundations.md @@ -4,7 +4,7 @@ description: Monetization foundations ---
- +
Introduction
@@ -23,13 +23,13 @@ Taken together, these components can foster a thriving economy within your exper ## Items
- +
Items and shop introduction

- +
Items

@@ -72,7 +72,7 @@ They can then be further divided into categories of utility: ## The shop
- +
The shop

@@ -124,7 +124,7 @@ New content and item updates invites players back to the store to see what's new ## Merchandising
- +
Merchandising
@@ -229,7 +229,7 @@ For out-of-the-box functionality to create bundles, see the [Bundles](../../reso ## Starter packs
- +
Starter packs
@@ -287,7 +287,7 @@ The starter pack should be merchandised as a special deal using price calculatio ## Season passes
- +
Season passes

diff --git a/.cursor/rules/roblox/en-us/production/game-design/onboarding-techniques.md b/.cursor/rules/roblox/en-us/production/game-design/onboarding-techniques.md index b66b0196..ae0bb1d6 100644 --- a/.cursor/rules/roblox/en-us/production/game-design/onboarding-techniques.md +++ b/.cursor/rules/roblox/en-us/production/game-design/onboarding-techniques.md @@ -3,7 +3,7 @@ title: Onboarding techniques description: Onboarding --- - +
diff --git a/.cursor/rules/roblox/en-us/production/game-design/onboarding.md b/.cursor/rules/roblox/en-us/production/game-design/onboarding.md index 2e36dab2..d8db2545 100644 --- a/.cursor/rules/roblox/en-us/production/game-design/onboarding.md +++ b/.cursor/rules/roblox/en-us/production/game-design/onboarding.md @@ -3,7 +3,7 @@ title: Onboarding description: Onboarding --- - +
diff --git a/.cursor/rules/roblox/en-us/production/game-design/prototyping.md b/.cursor/rules/roblox/en-us/production/game-design/prototyping.md index 02bccf59..e84abc05 100644 --- a/.cursor/rules/roblox/en-us/production/game-design/prototyping.md +++ b/.cursor/rules/roblox/en-us/production/game-design/prototyping.md @@ -3,7 +3,7 @@ title: Prototyping description: Prototyping --- - +
@@ -14,7 +14,7 @@ description: Prototyping ## Paper prototyping - +
@@ -49,7 +49,7 @@ Despite its benefits, prototyping on paper has drawbacks due to the difference i ## Studio prototyping - +
diff --git a/.cursor/rules/roblox/en-us/production/game-design/season-pass-design.md b/.cursor/rules/roblox/en-us/production/game-design/season-pass-design.md index d4c9a620..6c214264 100644 --- a/.cursor/rules/roblox/en-us/production/game-design/season-pass-design.md +++ b/.cursor/rules/roblox/en-us/production/game-design/season-pass-design.md @@ -3,7 +3,7 @@ title: Season pass design description: Teaches you about best practice guidance on designing season packs. --- - +
diff --git a/.cursor/rules/roblox/en-us/production/game-design/subscription-design.md b/.cursor/rules/roblox/en-us/production/game-design/subscription-design.md index 7cd549a6..2bacf7ae 100644 --- a/.cursor/rules/roblox/en-us/production/game-design/subscription-design.md +++ b/.cursor/rules/roblox/en-us/production/game-design/subscription-design.md @@ -3,7 +3,7 @@ title: Subscription design description: Learn how to effectively design subscriptions on Roblox. --- - +
diff --git a/.cursor/rules/roblox/en-us/production/game-design/ui-ux-design.md b/.cursor/rules/roblox/en-us/production/game-design/ui-ux-design.md index 576603ab..2c2429b0 100644 --- a/.cursor/rules/roblox/en-us/production/game-design/ui-ux-design.md +++ b/.cursor/rules/roblox/en-us/production/game-design/ui-ux-design.md @@ -3,7 +3,7 @@ title: UI and UX design description: UI and UX design in Roblox --- - +
The _user interface_ (UI) combines artistic visual design with communication-centric information design to produce menus, shop layouts, heads-up displays (HUDs) and other interfaces that players interact with. The _user experience_ (UX) relates to how players interact with the experience, how they make their choices known, and how they move from one choice to the next. While UI and UX often work collaboratively, UX carries a more significant focus on interactivity and the player's experience rather than the visual and informational design of the UI. diff --git a/.cursor/rules/roblox/en-us/production/monetization/immersive-ads.md b/.cursor/rules/roblox/en-us/production/monetization/immersive-ads.md index e731da03..bf18358c 100644 --- a/.cursor/rules/roblox/en-us/production/monetization/immersive-ads.md +++ b/.cursor/rules/roblox/en-us/production/monetization/immersive-ads.md @@ -18,11 +18,11 @@ The following ad formats can be served in your experience:
- +
Video ad format (autoplaying)
- +
Video ad format (click-to-play)
@@ -68,7 +68,7 @@ How publishers earn: - **Portal ads** are static, non-clickable images with a door that teleports users into an advertiser's experience. Advertisers bid on a teleport, so publishers earn for each successful teleport. A teleport is when a user enters the portal and arrives at the advertiser's experience. -To learn more about how advertisers are billed, see [Billing](../promotion/reporting-and-billing.md#billing). +To learn more about how advertisers are billed, see [Billing](../promotion/ads-manager.md#billing). Roblox pays out earnings on the 25th of the following month from when you inserted ad units into your experience. For example, if you insert ad units during the month of March, your payout date for the viewable impressions and successful teleports from those ad units is April 25. You can track your collective earnings from ads either through the **My Transactions** or the **Group Transactions** page. You can also analyze their overall performance through metrics graphs on the Creator Dashboard. @@ -107,7 +107,7 @@ Even if your experience is eligible to serve ads, not all users are eligible to ## Insert ad units - +

diff --git a/.cursor/rules/roblox/en-us/production/monetization/price-optimization.md b/.cursor/rules/roblox/en-us/production/monetization/price-optimization.md index 4a5588e5..e63cdc02 100644 --- a/.cursor/rules/roblox/en-us/production/monetization/price-optimization.md +++ b/.cursor/rules/roblox/en-us/production/monetization/price-optimization.md @@ -3,7 +3,7 @@ title: Price optimization description: Price optimization finds the best price points for your passes and developer products, helping you earn more money over time. --- - +
diff --git a/.cursor/rules/roblox/en-us/production/promotion/ads-manager.md b/.cursor/rules/roblox/en-us/production/promotion/ads-manager.md index 95cef49b..c544b983 100644 --- a/.cursor/rules/roblox/en-us/production/promotion/ads-manager.md +++ b/.cursor/rules/roblox/en-us/production/promotion/ads-manager.md @@ -3,61 +3,59 @@ title: Ads Manager description: The Ads Manager is where you can manage ad campaigns, ads reporting, and ads billings and payments in one place. --- - -This feature is in beta. - - The **Ads Manager** offers you control over your ad campaigns, empowering you to create, optimize, and measure ads effectively while reaching your campaign objectives. You can use this tool to manage your ad campaigns, ads reporting, and ads billings in one place. -With the [new Ads Manager](#manage-ads-new), you can create and manage ad campaigns for sponsored experiences that appear on a player's Home page. +
-With the [classic Ads Manager](#manage-ads-classic), you can create and manage ad campaigns for sponsored experiences, immersive ads inside experiences, and search ads that appear on Search results. + -## Create an ad account +## Set up an ad account -To access the Ads Manager, you must create an ad account with a verified email on a Roblox account registered for users aged 13 years or older. +To access the Ads Manager, you must set up an ad account with a verified email on a Roblox account registered for users aged 13 years or older. -When creating an account, you can choose between creating a personal or a business ads account. A personal account is for individuals who want to advertise on Roblox, while a business account manages a company's ad presence on Roblox. +When setting up an account, you can choose between creating a personal or a business ads account. A personal account is for individuals who want to advertise on Roblox, while a business account manages a company's ad presence on Roblox. -To create an ad account: +To set up an ad account: -1. Go to the [Ads Manager](https://ads.roblox.com) portal while signed into your Roblox account and **Create ad account**. -2. Choose a personal account or a business account. -3. Check the box to confirm the provided information and click **Create ad account**. +1. Create an ad account. + 1. Go to the [Ads Manager](https://ads.roblox.com) portal while signed into your Roblox account and click **Create ad account**. + 2. Choose a personal account or a business account. + 3. Check the box to confirm your information and click **Create ad account**. +2. Add a payment method to your ad account. + 1. Go to **Bills & Payments** > **Payment Settings**. + 2. Click **Add Payment Method**. + 3. Attach a credit or debit card to your account or buy ad credits. + - To add a card to your account, select the **Card** tab, enter your information, and click **Save and Authenticate**. This option is available for users 18 and above. A temporary $1.00 USD hold will be placed on the card and refunded after verification is complete within 7 business days. + - To buy ad credits, select the **Robux Ad Credit** tab, enter the amount of credits you want to purchase, and click **Buy**. You must buy a minimum of 1 ad credit. Converting Robux into ad credits to fund your campaigns is available for all users 13 and up. -## Add a payment method +
Robux to ad credit conversion
-Before you can create and manage ads on Roblox, you must first add a payment method to your ad account: + + Converting Robux to ad credit is a permanent and irreversible action. Once you convert Robux to ad credits, you can only spend your ad credits on ad campaigns within the Ads Manager. + -1. Go to **Payment Settings** in the Ads Manager. -2. Choose one of the two available payment methods. - 1. **Credit or Debit Card**: Credit or debit cards are available for users 18 and above. A temporary \$1.00 USD hold will be placed on the card and refunded after verification is complete within 7 business days. - 2. **Robux Ad Credit**: Converting Robux into ad credits to fund your campaigns is available for all users 13 and up. +Any Roblox user aged 13 and above can convert Robux to ad credits and use it for running ads. This accessibility ensures that a wide range of creators can participate in the advertising ecosystem. -### Convert Robux to ad credits - -Any Roblox user aged 13 and above can convert Robux to ad credit and use it for running ads. This accessibility ensures that a wide range of creators can participate in the advertising ecosystem. - -You can specify the amount of ad credit you want to purchase. When converting Robux to ad credits, consider the following: +When converting Robux to ad credits, consider the following: - 1 ad credit is equivalent to 263 Robux. -- 10 ad credits is the minimum conversion requirement. +- 1 ad credit is the minimum conversion requirement. This minimum conversion requirement streamlines the conversion process, prevents inaccuracies, and makes sure that you have enough ad credits to support meaningful advertising campaigns. - - Converting Robux to ad credit is a permanent and irreversible action. After you convert Robux to ad credits, you can only spend your ad credits on ad campaigns within the Ads Manager. - +## Manage your ads -## Manage ads (New) +Use the Ads Manager to create and manage ad campaigns for your experiences. With this tool, you can set budgets, select creatives, and control delivery settings while monitoring and adjusting your campaigns over time. - - The new Ads Manager is currently only available for sponsored experiences. - +### Ad campaign components -The new Ads Manager simplifies campaign creation to help you reach more players and maximize the impact of your ads. +Ad campaigns are made up of a few core components that control how your ads are delivered, how much you spend, and what players see. + +
Automated bidding
+ +With auto-bidding, you set an ad budget and duration and Roblox automatically calculates the bid that will get you the most plays at the lowest cost.
Budgets
@@ -68,306 +66,309 @@ When you create an ad campaign, you must set budgeting parameters to control cam You can pay for campaign budgets using either your debit or credit card on file, or your existing ad credit balance. If you fund a campaign with ad credits, you can't modify it after it's published. If you have unused ad credits after your campaign ends, those credits are refunded to your account. -
Automated bidding
+During campaign creation, you can enable **auto-reload** to automatically purchase ad credits when your account runs out. When auto-reload is triggered, Roblox reloads one day's worth of ad credits, and continues to reload daily as needed to keep your campaign running. -With auto-bidding, you set an ad budget and duration and Roblox automatically calculates the bid that will get you the most plays at the lowest cost. +
Creatives
-
Custom thumbnails
- -An ad creative is the thumbnail that shows up on a player's Home page when you sponsor an experience. You can select up to 5 thumbnails for your ad campaign, which are then evenly distributed across players' Home pages. After you create a campaign, you can edit the campaign to turn specific thumbnails on and off. +An ad creative is the thumbnail that shows up on a player's Home page when you sponsor an experience. You can select up to 10 thumbnails for your ad campaign, which are then evenly distributed across players' Home pages. After you create a campaign, you can edit the campaign to turn specific thumbnails on and off. You can use existing thumbnail images you have previously uploaded to the Creator Hub, or upload new ad-specific images with the Ads Manager. Any image you use as a thumbnail is resized to a ratio of 16:9 when displayed on the Home page. -### Define the campaign +### Create an ad campaign + + +Your ad campaign is automatically shown in both the Home page and search results. + -Campaigns for experiences that are not unique can result in **no ad spend** and **no conversions**. +Ad campaigns for experiences that are not unique can result in **no ad spend** and **no conversions**. Experiences with metadata and place files that closely resemble existing experiences on Roblox are not prioritized for recommendations and might rank lower in search results. Campaigns for these experiences might not be effective. -To create an ad campaign with the new Ads Manager: +To create an ad campaign: 1. Go to **Manage Ads** and click **Create Campaign**. -2. Under **Experience**, select the experience you want players to join when they click on your ad. -3. Under **Goal & Name**, enter a campaign name and select one of the following goals for the campaign: - - **Maximize Plays** to get the most plays at the lowest cost. - - **Acquire New Users** to reach players who have either never played your experience before or who haven't played it in the last 180 days. - - **Drive Retention** to turn visitors into regulars by re-engaging recent new players. - - **Reactivate Users** to reach players who have played your experience in the last 180 days but who haven't played in the last 30 days. -4. Under **Budget & Schedule**: +2. Under **Experience**: + 1. Select the experience you want players to join when they click on your ad. + 2. Enter a name for the campaign. +3. Under **Goal**, select a goal for the ad campaign: + + + + + + + + + + + + +
**Plays**Reach the players most likely to stay engaged with your experience.
(Coming soon) **Earnings**Reach the players most likely to spend money inside your experience.
+ +4. Under **Audience**: + 1. Select an audience for the ad campaign: + + + + + + + + + + + + + + + + + + + + +
**All Players**Show ad to all players, regardless of their past activity.
**New Players**Show ad to players who have never played your experience, or who haven’t played it in 180+ days.
**Recent Players**Show ad to players who have played your experience in the last 30 days. Only available for experiences with 10,000 recent players or more.
**Lapsed Players**Show ad to players who played your experience 30 to 180 days ago but haven’t returned. Only available for experiences with 20,000 lapsed players or more.
+ + 2. Under **Advanced Targeting**, narrow down your audience by customizing settings like location, age, gender, genre, and device type. +5. Under **Budget & Duration**: 1. Choose between a **Daily Budget** and a **Lifetime Budget**. 2. Select a **Payment Method**. If you're using ad credits, make sure the campaign budget does not exceed the available ad credits in your account. - 3. Set a **Duration** for your campaign. - 4. Set a **Start Date** and a **Start Time** for your campaign. -5. Under **Creative**, choose up to 5 thumbnails to show on players' Home page. -6. (Optional) Under **Audience Targeting**, customize the campaign's reach by only showing ads to players in specific locations and using specific devices. + 3. Set a **Start Date** and a **Start Time** for your campaign. + 4. Set a **Duration** for your campaign. + 5. If you're using ad credits, enable **auto-reload** to automatically add ad credits to the campaign when your budget runs out. +6. Under **Creatives**, choose up to 10 thumbnails to show players. 7. Click **Publish** and confirm submission. Your ad campaign will go live after it's approved by the moderation team. - Roblox tries to complete moderation within 24 hours for each ad submitted. Ads that do not pass moderation show the status of rejected. + Roblox tries to complete moderation within 24 hours for each ad submitted. Ads that do not pass moderation show the status of **rejected**. -## Manage ads (Classic) +### Edit an ad campaign -The classic Ads Manager gives you a more detailed way to create ad campaigns, including defining targeting and bidding parameters for ad sets, and creating immersive and search ads. - -An **ad campaign** is a coordinated series of ads designed to achieve a specific goal. To create an ad campaign with the Classic Ads Manager: - -1. [Define the campaign](#define-the-campaign). -2. [Define an ad set](#define-an-ad-set). -3. [Create ads](#create-ads). - -Before launching your campaign and submitting it to Roblox for moderation and approval, you'll be able to [review the campaign details](#review-the-campaign). - - - Advertising paid experiences and Restricted (18+) experiences is only available with sponsored and search ads. - - -### Define the campaign - -Campaigns are defined by their **campaign objective** and **budgeting and scheduling** parameters. Campaign objectives are divided into three categories: - -- **Awareness**: Campaigns focused on awareness show image or autoplaying video ads to increase awareness of your brand within an experience. -- **Visits**: Campaigns focused on visits aim to attract people to your experience on Roblox. These can take the form of either **sponsored experiences** on the Home page or **immersive ads** placed within portal ad units in experiences. You can't promote experiences with Restricted content maturity labels using the **Visits** objective. -- **Video Views**: Campaigns focused on 15-second click-to-play video views to engage audiences in-experience. - -Budgeting and scheduling parameters control campaign spending and duration. There are two different types of budgets: - -- **Daily budgets:** A daily budget is the maximum amount you pay for your ads per day. -- **Lifetime budgets:** A lifetime budget is the maximum amount you pay for your ads for the entire duration of the campaign. - -You can't set both a daily and lifetime budget. Budgets are paid for by either your credit card on file or with existing ad credit balance. - -To set up an ad campaign: - -1. Go to **Manage Ads (Classic)** and click **Create**. -2. Select your **Payment Method**. If you're using ad credits, make sure the campaign budget does not exceed the available ad credits in your account. Ad credits are debited after campaign submission based on your set budget. -3. Select a **Campaign Objective** from the dropdown. - - - -4. Choose a **Daily Budget** or **Lifetime Budget** for your campaign. -5. Choose the length of your campaign. - - - End dates are required for any campaign funded by ad credits. - - End dates are optional for daily budgets with debit and credit cards. If you don't set an end date, the campaign runs indefinitely using the daily budget. - -6. Enter a name for your campaign. -7. Click **Next**. - -### Define an ad set - -Ad sets are a group of ads within a campaign that share the same targeting and bidding parameters. When defining an ad set, you can customize the following three categories to meet the needs of your respective campaign goals: - -- **Audience settings**: Choose who sees your ad based on their geographical location, gender, age, and what device they're playing on. -- **Ad placement**: Determine where your ads are discoverable on the platform, such as in search results or within experiences. - -To define an ad set: - -1. Choose up to 10 regions or countries you want your ad to appear in. When you target a region, you automatically target every country within that region. - - - -2. Determine the gender and age range of the players you want to see your ads, as well as which devices you want your ads to appear on. Certain options might not be available in some locations. -3. Select where you want to place your ads according to your campaign objective. - - - For a **visits campaign objective**, choose between a sponsored experience on the Home page or an in-experience portal within an experience. - - For an **awareness campaign objective**, choose between an in-experience video or image. -4. Choose which genres you want to target with your ads. - - - For sponsored experiences, this represents the genre interests of your audience. - - For immersive ads, this represents the genre of the experiences your ads are displayed in. - -5. Determine a max bid price to show your ads to players through the available ad units placed in experiences. Bids are reflected as CPM (cost-per-thousand impressions), meaning that your max bid for CPM is the maximum amount you're willing to pay for every thousand impressions. -6. Enter a name for your ad set. -7. Click **Next**. - -To maximize your advertising reach and use both in-experience portals and sponsored experiences within the same campaign, consider creating an additional ad set. This flexibility enables you to experiment with different ad strategies and optimize your campaign's performance. - - - When you define your ad set, an audience estimation displays that indicates how many Roblox user accounts your ads can reach over a month when applying your targeting parameters and placements. It estimates a maximum number of users on the platform who might be exposed to your ads, but does not take into consideration your budget limits or bidding parameters. - - -
Bidding and auction
- -Ads on Roblox work in a bidding system, where you bid to have your ads shown to users through the available ad units placed in an experience. When determining your bidding settings, bids are reflected as CPM (cost-per-thousand impressions). Your max bid for CPM is the maximum amount you're willing to pay every thousand times your ad is seen by the user. A higher CPM can increase the chances of winning the auction, but it also means you pay more. - -At the same time, Roblox runs an auction to determine the best ad to show when there's an ad opportunity. You set the maximum price you're willing to pay as CPM or CPP (cost-per-play), then Roblox considers the player and ad information to generate an eCPM (effective cost-per-thousand impressions) value for each ad in the request. - -All eligible ads participate in a **second price auction**. The ad with the highest bid wins the ad slot, but only charges the price of the second highest price plus one cent. This process looks like this: - -1. You submit your bids for ad space. -2. Roblox calculates the eCPM value for each ad based on the player and ad information. -3. The ads are placed into an auction. -4. The ad with the highest eCPM value wins the auction. -5. The winning ad is displayed to the player. -6. You are charged the bid amount of the second highest price, plus one cent (\$0.01). - -For example, you want to display your ad on a website so you submit a bid of \$10. Another advertiser submits a bid of \$12 for their own ad and wins the auction because their bid is higher. They're then charged \$10.01, which is the price of the second highest bid (in this case, your bid) plus one cent. - -
Genre targeting
- -Genre targeting helps you target your ads to reach people who are more likely to engage with your experience. You can use your ad sets to target particular genres. - -
-
Experience genre
- -Experience genres are based on the genre of the experiences your [immersive ads](../../production/monetization/immersive-ads.md) are served in. For example,selecting only "Roleplaying" means your ads only appear in experiences classified as "Roleplaying."
- -
-
Audience genre
- -For **sponsored experiences**, audience genre targeting is based on user preferences. Ads are only served to users who like to play experiences in the selected genres. - -There are nine genres available for targeting: - -- **Action**: Complete physical challenges that require motor skills like jumping, shooting, and climbing. -- **Adventure**: Use clues and interact with people or the environment to progress gameplay. -- **Obby**: Navigate a series of challenging obstacles to reach a goal or complete a task. -- **Roleplaying**: Assume the roles of characters in a fictional setting and have freedom to influence the story. -- **Simulation**: Experiences that closely simulate real world or fictional realities. -- **Social**: An environment where characters can meet connections, hangout, and socialize. -- **Sports**: Play traditional or fictional physical sports. -- **Strategy**: Focus on skillful thinking and planning to achieve success. -- **Tycoon**: Take on the role of a business owner and manage various aspects of the business to achieve success and profitability. - - - Audience genre targeting isn't available when buying sponsored experiences to reach audiences in the EU. - - -### Create ads - -You can create three different types of ads using the Ads Manager: - -- **Sponsored experiences**, which appear as sponsored experience tiles on the Home page. -- Immersive ads, which include: - - **Portal ads**, which are static, non-clickable images within the 3D space of an experience, with a door that teleports a player into an advertiser's experience. - - **Image ads**, which are static, non-clickable images within the 3D space of an experience. - - **Video ads**, which are either auto-playing (non-rewarded) or click-to-play (can be rewarded) videos within the 3D space of an experience. -- **Search ads**, which allow you to promote your experience to users ages 13+ who are actively searching for experiences or genres of experiences using specific keywords. - -The ad type is determined by your [campaign objective](#define-the-campaign). For example, campaign objectives valuing awareness are displayed as image ads, while campaign objectives valuing visits are displayed as tile and portal ads. - -Roblox reviews each submitted ad prior to it being run. Make sure your ad is eligible to run by following the [advertising standards](./comply-with-advertising-standards.md). - -
Sponsored experiences
- -You can create a sponsored experience for all 13+ users and experiences by choosing the Visits campaign objective. - -To create a sponsored experience ad: - -1. Select the **Destination Experience** that you want the player to join. -2. Click **Upload file** and select the image you want to use for the ad. -3. Preview the image by clicking the expanding arrows over the image thumbnail. -4. Enter a name for your ad. -5. Click **Next**. - -
Portal ads
- - - - - The experience must include a button that lets players return to the original experience. - - -To create a portal ad: - -1. Select the **Destination Experience** that you want the player to land in after walking through the portal ad. -2. Click **Upload file** and select the image you want to use for the ad. -3. Preview the image by clicking the expanding arrows over the image thumbnail. You can also click **Live Preview** to see and interact with the portal ad like a player would. -4. Enter a name for your ad. -5. Click **Next**. - -
Image ads
- - - -To create an image ad: - -1. Click **Upload file** and select the image you want to use for the ad. -2. Preview the image by clicking the expanding arrows over the image thumbnail. You can also click **Live Preview** to see the image ad like a player would. -3. Enter a name for your ad. -4. Click **Next**. - -
Video ads
- -To create a video ad: - -1. Click **Upload media** and select the video you want to use for the ad. -2. Preview a static image of the video by clicking the expanding arrows over the image thumbnail. You can also click **Live Preview** to see the video ad like a player would. -3. Enter a name for your ad. -4. Click **Next**. - -
Search ads
- -Search ads have unique audience targeting, and a specific bidding and auction process for keywords. For more information, see [Search ads](./search-ads.md). - -
Live preview of ads
- -You can use live preview to see what your immersive ad looks like to the players inside an experience. Live preview is available for immersive ads in portal, image, and video formats. - -After selecting and uploading an image or video file, click **Live Preview** next to the image or video thumbnail. This takes you to a demo experience created by Roblox to teach users how to build and advertise on the Roblox platform. Inside the experience, you can see and interact with the ad format you selected in Ads Manager. - - - - - After you upload an image or video file, that file is submitted to Roblox for moderator approval. If approval is pending, a watermark displays on top of the live preview of your ad inside the demo experience. If Roblox rejects your file, the live preview of your ad doesn't show up inside the demo experience. - - -### Review the campaign - -With your campaign, ad set, and individual ad created, it's time to review your selections. This final screen lets you revisit and edit any previous setting of your campaign before launch. - -Review your ad campaign and click **Submit**. After you submission, moderators review it for approval. - - - Roblox tries to complete moderation within 24 hours for each ad submitted. Ads that do not pass moderation show the status of rejected. - - -## Edit a campaign - -After a campaign, ad set, or ad is submitted, you can still make adjustments to certain parameters. See the following for the parameters you can and can't change: +After a campaign is published, you can edit some fields while others are fixed: - - + + - + - - + + - - + + - - - - - - - - - - - - - +
ChangeableFixed**Changeable****Fixed**
Campaign nameCampaign objectiveGoal
Campaign end and start datesCampaign budget typeBudget amountAudience
Campaign budget amountAd set bid typeScheduleBudget type
Ad set bid amountAd set targeting parameters
Ad set name
Ad name
Ad typeCreatives
-## Cancel a campaign +### Cancel an ad campaign -You can cancel a campaign up to 6 hours before the campaign's scheduled start time. Cancelling a campaign automatically cancels any associated ad sets and ads, returns any ad credits you spent back to your account, and prevents your credit or debit card from being charged. +You can cancel a campaign up to 6 hours before the campaign's scheduled start time. + +Cancelling a campaign automatically cancels any associated ads, returns any ad credits you spent back to your account, and prevents your credit or debit card from being charged. + +## Reporting + +Reports provide insights into the overall effectiveness of your ad campaigns. You can use reporting data to compare performance across campaigns and identify opportunities to optimize. + +To view your reports, go to **Manage Ads** and select the date range and experience you want to analyze. + +The reporting metric cards include: + + + + + + + + + + + + + + + + + + + + + + + + + + +
**Metric card****Description**
**Amount Spent**The total amount of ad credits you have spent on all ad campaigns for the selected experience.
**Impressions**The total number of times all ads associated with the selected experience were shown to players.
**Plays**The total number of times players entered and started playing your experience as a result of all ads associated for the selected experience.
**7D Playtime**An estimate of the total time players spent in your experience over the last 7 days after converting through ads associated with the selected experience.
+ + + Ads only get credit for metrics like 7D Playtime when players enter your experience through an ad. + + + + +The reporting table includes: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
**Field****Description**
**Campaign**The name of the ad campaign. Campaigns with auto-reload enabled display an auto-reload icon next to the name.
**Off/On**A toggle indicating if the ad campaign is active or paused.
**Status**The status of the ad campaign. See the [Status](#status) table for more details.
**Spent**The total amount of USD or ad credits you have spent on the campaign.
**Impressions**The number of times your ad was shown to players.
**Clicks**The number of times players clicked on your ad on the Home and Search pages.
PlaysThe number of times players entered and started playing your experience as a result of the ad.
**CPP (Cost-per-play)**The average cost per play, calculated by dividing your total campaign spend by the number of plays.
**7D Playtime**An estimate of how much time players spent in your experience over the last 7 days after converting through an ad.
**30D Robux Earnings**An estimate of your total Robux earned over the past 30 days, based on players who converted through an ad during the selected date range. Excludes subscriptions, engagement payouts, and immersive ads.
+ + + +### Status + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
**Status****Description**
**In Review**Campaign has been created and will be reviewed within 24 hours.
**Moderated**Campaign has been moderated. This status includes a reason for the moderation.
**Active**Campaign is active and running as expected.
**Learning**The first 24 hours of an active campaign. During this time, the system continuously learns from engagement data to refine budget allocation.
**Scheduled**Campaign is scheduled to run at a future date.
**Inactive**Campaign is inactive.
**Completed**Campaign has reached its goal or end date.
**Auto-Completed**Campaign was stopped by the system after a period of time.
**Canceled**Campaign was manually stopped and removed from serving ads.
**Error**Campaign status can't be shown due to system error.
**Rejected**Campaign failed moderation review.
+ +## Billing + +The ads billing tool charges you for ad placements on Roblox using the payment method you have on file. To view billing information, go to **Billing & Payments** > **Payment Activity**. + +
Credit and debit cards
+ + +For first-time credit card users, \$5 USD will be charged upon campaign submission and used toward your first bill. Any unused balance will be refunded. + + +You can get charged at two different points when you use a credit or debit card: + +- When you reach your payment threshold +- On the first of the month if the payment threshold isn't reached + +Your account has a payment threshold that increases as you spend more on ads. When your ad spend reaches this threshold, your payment method on file is charged automatically. + +For example, if your account has a threshold of \$100 USD, your payment method is charged when your accrued ad spend reaches \$100. If you don't reach the threshold by the end of the month, any remaining balance is charged at the close of the monthly billing cycle. + +This means that if your campaigns reach the \$100 threshold on May 7, your payment method is charged \$100 on May 7. If your spend stays below $100, you're charged the outstanding amount at the end of the month instead. + +
Ad credits
+ +Ad credits are deducted in real time as your campaigns spend. Once per day, the total ad credit spend across all of your campaigns is combined into a **single daily charge**, which appears in your ad credit transaction history. Until this daily charge is finalized, any ad credit spend appears as **Pending** in your transaction history. + +Ad credits can have the following states: + +- **Purchased Ad Credit:** Transactions related to converting Robux into ad credit. This transparent categorization makes sure that you can easily track your ad credit acquisition. +- **Funded:** Ad credit allocated towards a campaign. Tracking this allocation allows you to monitor your campaign budget and spending. +- **Unused:** Ad credit allocated to a specific campaign but not used, which is returned on the campaign end date. This feature makes sure that your ad credits are used efficiently and returned when appropriate. +- **Ad Fraud Refund:** Any refunds applied back to your account. Refunds credited for a specific campaign remain locked to that campaign, not credited at the account level. + +
Ad fraud protection
+ +Roblox uses advanced detection methods for bots and other fraudulent activities to make sure that you don't pay for fraudulent traffic, and regularly adjusts billing and reporting to safeguard their interests. After 14 days from the campaign end date, campaigns are analyzed for fraudulent traffic, and transaction amounts are refunded accordingly. If invalid traffic is detected, refunds are applied 16 days after the campaign end date. This proactive approach helps maintain the integrity of your campaigns and ensures fair spending. + +Accounts responsible for ad fraud have their accounts suspended to prevent ongoing abuse. In addition, Roblox might suspend ad campaigns or advertiser accounts for non-payment of services properly rendered. Roblox expects you to act with integrity and follow the [advertising standards](./comply-with-advertising-standards.md). diff --git a/.cursor/rules/roblox/en-us/production/promotion/advertise-on-roblox.md b/.cursor/rules/roblox/en-us/production/promotion/advertise-on-roblox.md index 8efc2bc5..0df49f25 100644 --- a/.cursor/rules/roblox/en-us/production/promotion/advertise-on-roblox.md +++ b/.cursor/rules/roblox/en-us/production/promotion/advertise-on-roblox.md @@ -29,12 +29,12 @@ Which advertising product is right for your content depends on the type of conte Within the **[immersive ad units](../../production/monetization/immersive-ads.md)** publisher place within their experiences - [Search ads](../../production/promotion/search-ads.md) + [Search ads](../../production/promotion/ads-manager.md) Sponsored experience tiles based off of keywords and relevance Search results for experiences - [Sponsored experiences](../../production/promotion/ads-manager.md#sponsored-experiences) + [Sponsored experiences](../../production/promotion/ads-manager.md) All ages, 9+, 13+ experiences Within the **Sponsored** category on the [Home](https://www.roblox.com/home) page diff --git a/.cursor/rules/roblox/en-us/production/promotion/advertise.md b/.cursor/rules/roblox/en-us/production/promotion/advertise.md new file mode 100644 index 00000000..23da68ce --- /dev/null +++ b/.cursor/rules/roblox/en-us/production/promotion/advertise.md @@ -0,0 +1,146 @@ +--- +title: Advertising for creators +description: Grow your player base, increase your earnings, and invest in your growth. +hideInPageNavigation: true +--- + +export const sections = [ + { + description: "Advertising on Roblox gives you powerful ways to grow your audience, boost engagement, and increase your earning potential. Built with creator growth and earnings in mind, Roblox's ad system helps you reach players at the right moments, turn discovery into real gameplay, and support long-term monetization as your experience grows. Whether you're launching something new or expanding an established experience, ads are designed to help you connect with the players who are more likely to engage, return, and invest in what you build.", + column: true + }, + { + title: "Grow with ads", + stats: [ + { header: "150%", description: "lift in impressions for experiences that run ads" }, + { header: "24%", description: "increase in plays" }, + { header: "16%", description: "increase in playtime" } + ], + description: "Ads Manager is Roblox's self-service advertising platform, designed to support creators of all sizes as they grow on the platform. By advertising on the Home page and in Search results, you can reach and retain players who are interested in playing your experience.", + row: true, + video: "https://www.youtube-nocookie.com/embed/5HcH-9E7USc?si=IDla-YBxiO_E-O0q", + content: [ + { + title: "Get your game discovered", + description: "Whether you've just published an experience or you're ready to take an existing one to the next level, Ads Manager helps you drive awareness, highlight new content, and find new audiences." + }, + { + title: "Improved your retention efforts", + description: "Ads Manager audiences make it easier to reach specific groups of players, including new, recent, and lapsed players. Re-engage players who have already shown interest in your experience and give them a reason to come back and play again." + }, + { + title: "Control your growth", + description: "Unlike organic discovery, you're in control of the ads you run. With Ads Manager, you can ramp traffic up or down to test new features, support live updates, or scale quickly when you're ready to grow. You can also run always-on campaigns to continuously optimize your user funnel. This flexibility helps you experiment, iterate, and respond to player behavior in real time." + }, + { + links: [ + { text: "Ads Manager", href: "./production/promotion/ads-manager" } + ] + } + ] + }, + { + title: "Start earning with ads", + row: true, + video: "https://www.youtube-nocookie.com/embed/-HYByqvW2uc", + content: [ + { + title: "Deploy in-game ads", + description: "Placing ads inside your experience can help increase earnings and diversify monetization by letting you earn from both paying and non-paying players. Simply deploy ads in your experience and let Roblox handle delivery and earnings.", + }, + { + description: "Choose between ad formats like Rewarded Videos, which let you offer in-experience rewards to incentivize players to watch click-to-play video ads, Billboards, which display image or video ads, and Portals, which combine an image and an interactive door that teleports players to an advertised experience." + }, + { + links: [ + { text: "Rewarded Video", href: "./production/promotion/rewarded-video-ads" }, + { text: "Billboards", href: "./production/monetization/immersive-ads#billboards" }, + { text: "Portals", href: "./production/monetization/immersive-ads#portal-ads" } + ] + } + ] + } +]; + + {sections.map((section, index) => ( + + {section.title && ( + {section.title} + )} +
+ {section.description && ( +

{section.description}

+ )} + {section.buttons && section.buttons.map((button, btnIndex) => ( + + ))} +
+ {section.stats && ( + + + {section.stats.map((stat, statIndex) => ( + + + + {stat.header} + {stat.description} + + + + ))} + + + )} + { section.row && section.content && ( + + + { section.content.map((section, index) => ( +
+

{section.title}

+

{section.description}

+
+ {section.links && section.links.map((link, linkIndex) => ( + + {link.text}
+
+ ))} + {section.buttons && section.buttons.map((button, btnIndex) => ( + + ))} +
+
+ ))} +
+ + + +
+ )} +
+ ))} diff --git a/.cursor/rules/roblox/en-us/production/promotion/index.md b/.cursor/rules/roblox/en-us/production/promotion/index.md index ea09f750..bd5010f2 100644 --- a/.cursor/rules/roblox/en-us/production/promotion/index.md +++ b/.cursor/rules/roblox/en-us/production/promotion/index.md @@ -22,7 +22,7 @@ The following table details promotional methods for experiences on the platform. **Search ads** Promote your experiences in search results by creating search ads. This form of advertising allows developers to target their ads to users using search, increasing the likelihood of engagement based off of specific keywords. -

For more information, see [Search ads](../../production/promotion/search-ads.md). +

For more information, see [Ads Manager](../../production/promotion/ads-manager.md). **Sponsored experiences** diff --git a/.cursor/rules/roblox/en-us/production/promotion/referral-system.md b/.cursor/rules/roblox/en-us/production/promotion/referral-system.md index c841097b..f8c9fc6f 100644 --- a/.cursor/rules/roblox/en-us/production/promotion/referral-system.md +++ b/.cursor/rules/roblox/en-us/production/promotion/referral-system.md @@ -10,8 +10,8 @@ If you previously used this feature while it was still in beta, make sure to imp - - + +
diff --git a/.cursor/rules/roblox/en-us/production/promotion/rewarded-video-ads.md b/.cursor/rules/roblox/en-us/production/promotion/rewarded-video-ads.md index bbc53891..fe27a316 100644 --- a/.cursor/rules/roblox/en-us/production/promotion/rewarded-video-ads.md +++ b/.cursor/rules/roblox/en-us/production/promotion/rewarded-video-ads.md @@ -3,7 +3,7 @@ title: Rewarded video ads description: Immersive ads allow you insert ad units into your experience that programmatically serve ad content. --- - +

@@ -27,7 +27,7 @@ Before implementing rewarded video ads, consider where inside your experience yo

- +

@@ -220,13 +220,13 @@ local adButton = Instance.new("TextButton", screenGui) -- Register the button with AdService local success, err = pcall(function() --- The second parameter is an optional Placement ID (UUID) parameter generated in the Creator Hub. --- If you choose not to provide a Placement ID, the ad opportunity is tracked under the default placement. - AdService:RegisterAdOpportunityAsync(adButton, "123e4567-e89b-12d3-a456-426614174000") + -- The second parameter is an optional Placement ID (Number) parameter generated in the Creator Hub. + -- If you choose not to provide a Placement ID, the ad opportunity is tracked under the default placement. + AdService:RegisterAdOpportunityAsync(adButton, 1234567891234567) end) if not success then - warn("Failed to register ad opportunity:", err) + warn("Failed to register ad opportunity:", err) end ``` diff --git a/.cursor/rules/roblox/en-us/production/promotion/search-ads.md b/.cursor/rules/roblox/en-us/production/promotion/search-ads.md index b0789ac1..992a58b7 100644 --- a/.cursor/rules/roblox/en-us/production/promotion/search-ads.md +++ b/.cursor/rules/roblox/en-us/production/promotion/search-ads.md @@ -81,7 +81,7 @@ To create search ads: 6. In the Review Campaign page, review the final details of your advertisement and click **SUBMIT** to launch your campaign. -After launching your campaign, you can monitor the campaign's performance with [ads reporting](#reporting) and [billing](./reporting-and-billing.md#billing). +After launching your campaign, you can monitor the campaign's performance with [ads reporting](#reporting) and [billing](./ads-manager.md#billing). ## Bidding and auction @@ -113,6 +113,6 @@ The following is the [same bidding and auction information](./ads-manager.md#bid ## Reporting -You can review your ad campaign's performance using the Ad Manager's [ads reporting tool](./reporting-and-billing.md#reporting). At this time, you can't filter reports by keywords, but you can create ad sets with a single keyword to compare how an individual keyword performs for your campaign. +You can review your ad campaign's performance using the Ad Manager's [ads reporting tool](./ads-manager.md#reporting). At this time, you can't filter reports by keywords, but you can create ad sets with a single keyword to compare how an individual keyword performs for your campaign. Search ad metrics also populate in the [Analytics Dashboard](../analytics/acquisition.md#acquisition-sources) acquisition metrics. At this time, search ad and sponsored ad results are combined as a single Sponsored Ad metric on acquisition reports. diff --git a/.cursor/rules/roblox/en-us/production/publishing/publish-experiences-and-places.md b/.cursor/rules/roblox/en-us/production/publishing/publish-experiences-and-places.md index 415ede01..df270ce8 100644 --- a/.cursor/rules/roblox/en-us/production/publishing/publish-experiences-and-places.md +++ b/.cursor/rules/roblox/en-us/production/publishing/publish-experiences-and-places.md @@ -10,7 +10,7 @@ Places are comparable to scenes in Unity or maps in Unreal Engine.
- +
Many creators create additional places within an experience to organize assets for different gameplay areas. For example, if you want players to join a dungeon before [teleporting](../../projects/teleport.md) to either a vast desert or spooky island, you can organize the assets for each area into their own place. diff --git a/.cursor/rules/roblox/en-us/production/publishing/thumbnails.md b/.cursor/rules/roblox/en-us/production/publishing/thumbnails.md index e2cccf97..c1cf1dc6 100644 --- a/.cursor/rules/roblox/en-us/production/publishing/thumbnails.md +++ b/.cursor/rules/roblox/en-us/production/publishing/thumbnails.md @@ -178,7 +178,7 @@ After you set up and activate thumbnail personalization, its algorithm shows eac
- + ### Set up thumbnail personalization diff --git a/.cursor/rules/roblox/en-us/projects/assets/packages.md b/.cursor/rules/roblox/en-us/projects/assets/packages.md index 891db195..ce36a776 100644 --- a/.cursor/rules/roblox/en-us/projects/assets/packages.md +++ b/.cursor/rules/roblox/en-us/projects/assets/packages.md @@ -13,7 +13,7 @@ To keep assets organized and reusable across your team or across multiple projec The most efficient workflow is to [create a package](#create-packages), [share it](#share-and-access-levels) with any collaborators, and [set it to auto-update](#automatic-updates). And you don't have to wait for a model to be "done" before using it in a package. Even if the package is a placeholder on top of a simple shape, you can use it to [greybox your environment](../../tutorials/curriculums/environmental-art/greybox-your-environment.md) and then have the placeholder copies automatically update as you publish more detailed versions.

- + ## Create packages diff --git a/.cursor/rules/roblox/en-us/projects/data-model.md b/.cursor/rules/roblox/en-us/projects/data-model.md index 4bee683e..3849c63e 100644 --- a/.cursor/rules/roblox/en-us/projects/data-model.md +++ b/.cursor/rules/roblox/en-us/projects/data-model.md @@ -3,7 +3,7 @@ title: Data model description: Explains the hierarchy of objects that describe everything about a place. --- - +
@@ -21,7 +21,7 @@ Runtime](/projects/client-server). ## Objects - +
diff --git a/.cursor/rules/roblox/en-us/projects/teleport.md b/.cursor/rules/roblox/en-us/projects/teleport.md index 8071cc7d..82e6fe12 100644 --- a/.cursor/rules/roblox/en-us/projects/teleport.md +++ b/.cursor/rules/roblox/en-us/projects/teleport.md @@ -3,44 +3,80 @@ title: Teleport between places description: Explains how to use TeleportService to teleport users between different places in your experience. --- -If you want to build an experience with many distinct places, such as a fantasy world with multiple towns, castles, dungeons, and a vast forest, you can use `Class.TeleportService` to enable users to teleport between places in a universe, servers, or even to another experience. +Many experiences are subdivided into multiple [places](../production/publishing/publish-experiences-and-places.md#create-additional-places), such as a fantasy world with towns, castles, dungeons, and a vast forest. Use `Class.TeleportService` to teleport users between places, to different servers, or even to other experiences. -`Class.TeleportService` doesn't support playtesting in Roblox Studio. You must publish the experience and use it on the Roblox application for testing. +`Class.TeleportService` doesn't support playtesting in Roblox Studio. You must publish the experience and test in the Roblox client. -## Set up teleportation +## Teleport players -To enable teleportation in your experience, use `Class.TeleportService:TeleportAsync()`. The method accepts three parameters: +To teleport players, use `Class.TeleportService:TeleportAsync()`. This method accepts three parameters: - The `Class.DataModel.PlaceId|PlaceId` for users to teleport to. -- An array containing the `Class.Player` instances representing the users to teleport. +- An array containing the `Class.Player` instances you want to teleport. - An optional `Class.TeleportOptions` instance that contains custom properties for the `Class.TeleportService:TeleportAsync()|TeleportAsync()` call. ```lua local Players = game:GetService("Players") local TeleportService = game:GetService("TeleportService") -local TARGET_PLACE_ID = 1234 -- replace with your own place ID - +local TARGET_PLACE_ID = 12345678901234 -- replace with your own local playerToTeleport = Players:GetPlayers()[1] -- get the first user in the experience -TeleportService:TeleportAsync(TARGET_PLACE_ID, {playerToTeleport}, teleportOptions) +TeleportService:TeleportAsync(TARGET_PLACE_ID, {playerToTeleport}) ``` - -You can only call `Class.TeleportService:TeleportAsync()|TeleportAsync()` from server-side scripts. This limitation reduces client-side exploitation. If necessary, you can call `Class.TeleportService:Teleport()|Teleport()` from client-side scripts, but `Class.TeleportService:TeleportAsync()|TeleportAsync()` is the recommended method. +To get the appropriate players to teleport, you might use a `Class.BasePart.Touched` or a `Class.ProximityPrompt.Triggered` event to get an individual `Class.Player`. Then you can check if the player is part of a team (`Class.Player.Team`) or party (`Class.Player.PartyId`). Finally, you can use `Class.Team:GetPlayers()` or `Class.SocialService:GetPlayersByPartyId()` if you want to teleport the entire group rather than just the individual. + + +To reduce client-side exploits, you can only call `Class.TeleportService:TeleportAsync()|TeleportAsync()` from server scripts. If necessary, client scripts can call `Class.TeleportService:Teleport()|Teleport()`, but we don't recommend it. For more information, see [Configure secure teleportation](#configure-secure-teleportation). -If you want to take precautions of handling errors when setting up teleportation, see how to [handle failed teleports](#handle-failed-teleports). +## Configure secure teleportation -### Enable cross experience teleportation +Three settings handle teleport security. -For security purposes, teleporting a user from your experience to another experience owned by others fails by default. To enable cross experience teleportation, open the **Security** section of Studio's **File** ⟩ **Experience Settings** window and enable **Allow Third Party Teleports**. +Setting | Description +:--- | :--- +(Creator Dashboard) **Experience** > **Access Settings** > **Access Control for Places** | Controls whether players can join any place in your experience or must first join the [start place](../production/publishing/publish-experiences-and-places.md#create-experiences). +(Creator Dashboard) **Place** > **Access** > **Direct Access Control** | Overrides your experience-level **Access Control for Places** setting for a non-start place. +(Studio) **File** > **Experience Settings** > **Security** > **Allow Third Party Teleports** | Controls teleports from your experience to **experiences that you don't own**. You can leave this setting disabled and still teleport players between published experiences you own. + +**Access Control for Places** controls players teleporting **into** your experience and is the most critical setting for preventing teleport-based exploits. + +![Access control for places on the Creator Hub](../assets/players/teleport-access-control.png) + +- If you choose **Fully open**, players can join any place in your experience through teleports from any experience, including deep links, game invites, joining a connection, and more. + + This is a good choice if your experience has several places and you want friends to be able to easily join each other no matter which place they're in. + +- If you choose **Limited to same universe**, players can only join non-start places through teleports within your experiences. This setting allows both client- and server-initiated teleports. + + This is a good choice if you have a legacy experience that you don't want to [migrate to secure teleports](#migrate-to-secure-teleports). + +- If you choose **Secure within universe only**, players can only join non-start places through server-initiated teleports within this experience. + + This is a good choice if your experience has a strict progression system before players can access certain areas. It's also a good choice if your experience has a test place that players shouldn't have access to or for places that exclusively use reserved servers. + + +Ultimately, your **Access Control for Places** setting depends on the type of experience you want to build. Many experiences don't need secure teleports. + + +### Migrate to secure teleports + +If you have an existing experience that uses client-side teleports and want to require server-initiated teleports, the goal is to move all teleport logic out of client scripts and into server scripts: + +1. Find all client scripts that call `Class.TeleportService:Teleport()|Teleport()`. +1. Change these calls to instead fire [remote events](../scripting/events/remote.md). Alternatively, you can change the calls to instead use `Class.ProximityPrompt|ProximityPrompts`, `Class.ClickDetector|ClickDetectors`, or even just the `Class.BasePart.Touched` event. +1. Reimplement the teleport in a server script using `Class.TeleportService:TeleportAsync()|TeleportAsync()`. +1. When no more `Class.TeleportService:Teleport()|Teleport()` calls exist, change **Access Control for Places** to **Secure**. ## Create custom teleport screens -When a user triggers a teleport, they see the standard Roblox loading screen as they wait for the new place to load in. You can add a custom teleport screen to improve immersion for users by calling `Class.TeleportService:SetTeleportGui()` on the client and pass through the `Class.ScreenGui` to use before teleporting the user. The following example sets a customized `Class.ScreenGui` located in `Class.ReplicatedStorage` as the loading screen when a teleport happens. It doesn't run any scripts inside of the `Class.ScreenGui`. +When a user triggers a teleport, they see the standard Roblox loading screen as they wait for the new place to load. If desired, you can add a custom teleport screen by calling `Class.TeleportService:SetTeleportGui()` on the client. + +The following example sets a customized `Class.ScreenGui` from `Class.ReplicatedStorage`. Any scripts within the `Class.ScreenGui` do **not** run. ```lua local TeleportService = game:GetService("TeleportService") @@ -57,7 +93,7 @@ You can customize teleportations, such as [teleporting users to a specific serve ### Teleport to specific servers -To teleport users to specific servers, set the target server using `Class.TeleportOptions` and pass it to the `Class.TeleportService:TeleportAsync()` method. If you don't specify a server, users are teleported into a matchmade public server. The information of the first user in the list is used to matchmake to that public server. +To teleport users to specific servers, set the target server using `Class.TeleportOptions` and pass it to the `Class.TeleportService:TeleportAsync()|TeleportAsync()` method. If you don't specify a server, users are teleported into a public server; the information of the first user in the list is used for matchmaking. To teleport users to a specific public server, set the `Class.TeleportOptions.ServerInstanceId` property as a valid instance ID, which is a unique identifier for a public server. @@ -82,15 +118,11 @@ teleportOptions.ShouldReserveServer = true ### Send user data along with teleports -Teleporting a user between places discards any local data associated with that user. You can use the following approaches to handle data persistence between places. +Teleporting a user between places discards any local data associated with that user. You can use the following approaches to handle data persistence between places: - If your experience utilizes **secure** user data like in-experience currency or inventory, implement [data stores](../cloud-services/data-stores) or [memory stores](../cloud-services/memory-stores/index.md) to maintain data from place to place. -- To send basic **non-secure** data from place to place, call `Class.TeleportOptions:SetTeleportData()` before passing it to `Class.TeleportService:TeleportAsync()|TeleportAsync()`. - - -Don't pass secure data using `Class.TeleportOptions:SetTeleportData()` because it has the risk of exploitation. - +- To send basic **non-secure** data from place to place, call `Class.TeleportOptions:SetTeleportData()` before passing it to `Class.TeleportService:TeleportAsync()|TeleportAsync()`. **Don't** pass secure data using this method; the data is visible to the client and unencrypted. ```lua local teleportData = { @@ -101,7 +133,7 @@ local teleportOptions = Instance.new("TeleportOptions") teleportOptions:SetTeleportData(teleportData) ``` -To get all data of a user arriving from a teleport on the server, use the `Class.Player:GetJoinData()` function, which returns a dictionary including the data associated with the user. +To retrieve all data when a user arrives at the new place after a teleport, use the `Class.Player:GetJoinData()` function, which returns a dictionary with a `TeleportData` key. ```lua local Players = game:GetService("Players") @@ -111,7 +143,7 @@ local function onPlayerAdded(player) local teleportData = joinData.TeleportData local randomNumber = teleportData.randomNumber - print(player.Name .. "joined with the number" .. randomNumber) + print(player.Name .. " joined with the number " .. randomNumber) end Players.PlayerAdded:Connect(onPlayerAdded) @@ -121,11 +153,11 @@ To retrieve only the teleport data on the client, you can use `Class.TeleportSer ## Handle failed teleports -Like any API call that involves network requests, teleports can fail and throw an error. Wrap them in protected calls (`Global.LuaGlobals.pcall()`). Some failures benefit from retries, particularly those involving reserved servers, so we recommend retrying some number of times on failures. +Like any API call that involves network requests, teleports can fail and throw an error. Wrap them in protected calls (`Global.LuaGlobals.pcall()`). Some failures benefit from retries, particularly those involving reserved servers, so we recommend retrying some number of times on failure. Even if a call succeeds and the teleport initiates, it can still fail at the last moment without throwing an error and leave the user in the server. When this happens, it triggers the `Class.TeleportService.TeleportInitFailed` event. -The following example `Class.ModuleScript` defines a `SafeTeleport` function to teleport the user in a protected call with retry logic. It also has a `handleFailedTeleport` function to deal with situations in which the call was successful, but the teleport didn't occur. +The following example `Class.ModuleScript` returns a single `SafeTeleport` function that teleports players in a protected call with retry logic. It also has a `handleFailedTeleport` function to deal with situations in which the call was successful, but the teleport didn't occur. ```lua local TeleportService = game:GetService("TeleportService") @@ -173,17 +205,24 @@ TeleportService.TeleportInitFailed:Connect(handleFailedTeleport) return SafeTeleport ``` -The `SafeTeleport` function receives the same arguments as the `Class.TeleportService:TeleportAsync()|TeleportAsync()` function. You can use the following `Class.ModuleScript` with the `SafeTeleport` function to perform teleports from anywhere in your experience to reduce failed teleports. +The `SafeTeleport` function receives the same arguments as the `Class.TeleportService:TeleportAsync()|TeleportAsync()` function. You can use the following script with the `SafeTeleport` function to perform teleports from anywhere in your experience: ```lua local Players = game:GetService("Players") +local TeleportService = game:GetService("TeleportService") local ServerScriptService = game:GetService("ServerScriptService") local SafeTeleport = require(ServerScriptService.SafeTeleport) -local TARGET_PLACE_ID = 1818 -- replace with your own place ID +local PLACE_TO_TELEPORT_TO = 12345678 -local playerToTeleport = Players:GetPlayers()[1] -- get the first user in the game +local function teleport(touchPart) + local playerToTeleport = game.Players:GetPlayerFromCharacter(touchPart.Parent) -SafeTeleport(TARGET_PLACE_ID, {playerToTeleport}, teleportOptions) + if playerToTeleport then + SafeTeleport(PLACE_TO_TELEPORT_TO, {playerToTeleport}) + end +end + +script.Parent.Touched:Connect(teleport) ``` diff --git a/.cursor/rules/roblox/en-us/reference/engine/STUDIO_VERSION b/.cursor/rules/roblox/en-us/reference/engine/STUDIO_VERSION index cc6f68a5..4ec4c834 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/STUDIO_VERSION +++ b/.cursor/rules/roblox/en-us/reference/engine/STUDIO_VERSION @@ -1,2 +1,2 @@ -0.706.0.7060750 -version-dabb43efc3a944c6 \ No newline at end of file +0.707.0.7070732 +version-207b4196e6334893 \ No newline at end of file diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/AnimationTrack.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/AnimationTrack.yaml index 08a7d224..6ee17743 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/AnimationTrack.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/AnimationTrack.yaml @@ -483,7 +483,7 @@ methods: default: summary: '' returns: - - type: Instance + - type: Instance? summary: '' tags: [] deprecation_message: '' @@ -626,7 +626,7 @@ methods: default: summary: '' - name: target - type: Instance + type: Instance? default: summary: '' returns: diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/AudioDeviceInput.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/AudioDeviceInput.yaml index bb541e9d..dc0efeb9 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/AudioDeviceInput.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/AudioDeviceInput.yaml @@ -120,23 +120,6 @@ properties: can_load: true can_save: true capabilities: [] - - name: AudioDeviceInput.MutedByLocalUser - summary: '' - description: '' - code_samples: [] - type: boolean - tags: - - NotReplicated - deprecation_message: '' - security: - read: RobloxScriptSecurity - write: RobloxScriptSecurity - thread_safety: ReadSafe - category: Recording - serialization: - can_load: false - can_save: false - capabilities: [] - name: AudioDeviceInput.Player summary: | Determines whose device is producing sound. diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/AudioEmitter.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/AudioEmitter.yaml index 704aa30b..38fcad75 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/AudioEmitter.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/AudioEmitter.yaml @@ -122,23 +122,6 @@ properties: can_save: true capabilities: - Audio - - name: AudioEmitter.PositionOverride - summary: '' - description: '' - code_samples: [] - type: Instance - tags: [] - deprecation_message: '' - security: - read: RobloxEngineSecurity - write: RobloxEngineSecurity - thread_safety: ReadSafe - category: Data - serialization: - can_load: true - can_save: true - capabilities: - - Audio - name: AudioEmitter.SimulationFidelity summary: | Controls how detailed the audio simulation should be for this diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/AudioListener.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/AudioListener.yaml index efb85b0f..e22e5ace 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/AudioListener.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/AudioListener.yaml @@ -121,23 +121,6 @@ properties: can_save: true capabilities: - Audio - - name: AudioListener.PositionOverride - summary: '' - description: '' - code_samples: [] - type: Instance - tags: [] - deprecation_message: '' - security: - read: RobloxEngineSecurity - write: RobloxEngineSecurity - thread_safety: ReadSafe - category: Data - serialization: - can_load: true - can_save: true - capabilities: - - Audio - name: AudioListener.SimulationFidelity summary: | Controls how detailed the audio simulation should be for this diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/AudioPlayer.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/AudioPlayer.yaml index 95585b7b..89a300ed 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/AudioPlayer.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/AudioPlayer.yaml @@ -129,23 +129,6 @@ properties: can_save: true capabilities: - Audio - - name: AudioPlayer.IsMutedForCapture - summary: '' - description: '' - code_samples: [] - type: boolean - tags: [] - deprecation_message: '' - security: - read: RobloxScriptSecurity - write: RobloxScriptSecurity - thread_safety: ReadSafe - category: Data - serialization: - can_load: true - can_save: true - capabilities: - - Audio - name: AudioPlayer.IsPlaying summary: | Denotes whether this `Class.AudioPlayer` is currently playing. diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/AvatarCreationService.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/AvatarCreationService.yaml index 0fcd4bf6..6b57e97a 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/AvatarCreationService.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/AvatarCreationService.yaml @@ -23,7 +23,7 @@ properties: [] methods: - name: AvatarCreationService:AutoSetupAvatarAsync summary: | - Automatically sets up a custom `Class.Model` as an avatar asset. + Automatically sets up a custom `Class.Model` and/or avatar accessories. description: | Automatically sets up a custom `Class.Model` as an avatar asset. This method returns a `string` generation ID which can be passed to @@ -49,11 +49,12 @@ methods: default: summary: | The `Class.Player` that the avatar is being set up for. - - name: model + - name: autoSetupParams type: Dictionary default: summary: | - The humanoid `Class.Model` that will be set up as an avatar. + A table containing the arguments. Type: + `type AutoSetupAccessory = { AccessoryType: Enum.AccessoryType, IsLayered: bool, Instance: Model, } type AutoSetupParams = { Body: Model?, Accessories: {AutoSetupAccessory}, }` - name: progressCallback type: Function? default: diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/AvatarEditorService.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/AvatarEditorService.yaml index 98406047..569b2116 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/AvatarEditorService.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/AvatarEditorService.yaml @@ -32,6 +32,327 @@ description: | second to these `AvatarEditorService` endpoints, regardless of the number of servers or user count. Exceeding these limits returns a `429 Too Many Requests` error. + + #### Item Details Response + + The following methods return item data in a shared response format: + + - `Class.AvatarEditorService:GetItemDetailsAsync()` + - `Class.AvatarEditorService:GetBatchItemDetailsAsync()` + - `Class.AvatarEditorService:SearchCatalogAsync()` + + ```lua + { + "Id": 0, + "ItemType": "Asset", + "AssetType": "Image", + "BundleType": "BodyParts", + "Name": "string", + "Description": "string", + "ProductId": 0, + "ItemStatus": ["New"], + "ItemRestrictions": ["Collectible"], + + "BundledItems": [ + { + "Id": 0, + "Name": "string", + "Type": "Asset", + "AssetType": 29 + } + ], + "IsRecolorable": false, + + "CollectibleItemId": "string", + "TotalQuantity": 0, + "UnitsAvailableForConsumption": 0, + "QuantityLimitPerUser": 0, + "HasResellers": false, + "OffSaleDeadline": null, + + "Price": 0, + "PremiumPricing": { + "PremiumDiscountPercentage": 0, + "PremiumPriceInRobux": 0 + }, + "LowestPrice": 0, + "LowestResalePrice": 0, + "PriceStatus": "string", + "SaleLocationType": "ShopAndAllExperiences", + "PurchaseCount": 0, + "FavoriteCount": 0, + + "CreatorType": "User", + "CreatorTargetId": 0, + "CreatorName": "string", + "CreatorHasVerifiedBadge": false + } + ``` + + ##### Basic Information + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
IdnumberThe unique identifier of the item.
ItemTypestringThe type of item: "Asset" or "Bundle". Corresponds to Enum.AvatarItemType.
AssetTypestringThe asset type. Corresponds to Enum.AvatarAssetType values (e.g., "Hat", "Shirt"). Only present if ItemType is "Asset".
BundleTypestringThe bundle type. Corresponds to Enum.BundleType values (e.g., "BodyParts", "Animations"). Only present if ItemType is "Bundle".
NamestringThe display name of the item.
DescriptionstringThe item's description text.
ProductIdnumberThe product ID associated with this item.
ItemStatusarrayAn array of status strings (e.g., "New", "Sale", "XboxExclusive", "AmazonExclusive").
ItemRestrictionsarrayAn array of restriction strings. See the itemRestrictions table below.
+ + ##### Bundle Information + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
BundledItemsarrayAn array of items contained in the bundle. Only present if ItemType is "Bundle". Each entry contains:
Id: The unique identifier of the bundled item.
Name: The display name of the bundled item.
Type: The type of the bundled item (e.g., "Asset").
AssetType: The asset type as an integer. Corresponds to Enum.AvatarAssetType.
Owned: Whether the bundled item is owned by the current user. Only present in Class.AvatarEditorService:GetItemDetailsAsync().
IsRecolorablebooleanWhether the bundle supports skin tone matching. Only applies to BodyParts and DynamicHead bundles.
+ + ##### Collectible Information + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
CollectibleItemIdstringThe unique item ID of the collectible.
TotalQuantitynumberThe total quantity of the collectible available for purchase (not resale).
UnitsAvailableForConsumptionnumberThe number of units available for purchase. Only applies to Limited items with remaining stock.
QuantityLimitPerUsernumberMaximum number of the same collectible item a user can own.
HasResellersbooleantrue when item is a Limited collectible and there are copies available for resale.
OffSaleDeadlinestringThe date/time when the item goes off sale.
+ + ##### Pricing and Sale Information + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
PricenumberThe price in Robux. 0 if free or not for sale.
PremiumPricingtablePremium pricing information. Contains the following fields:
PremiumDiscountPercentage: The discount percentage for Premium members.
PremiumPriceInRobux: The discounted price in Robux for Premium members.
LowestPricenumberThe lowest resale price for Limited items.
LowestResalePricenumberThe lowest resale price for the collectible in Robux.
PriceStatusstringThe price status (e.g., "Free", "Off Sale", "No Resellers").
SaleLocationTypestringThe type of sale location setting. See SaleLocationType values below.
PurchaseCountnumberThe total number of times this item has been purchased.
FavoriteCountnumberThe total number of users who have favorited this item.
+ + ##### Creator Information + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
CreatorTypestringEither User or Group. See Enum.CreatorType.
CreatorTargetIdnumberThe ID of the creator user or group.
CreatorNamestringThe display name of the creator.
CreatorHasVerifiedBadgebooleanBoolean of whether the creator has a verified badge.
+ + ##### SaleLocationType Values + + | Value | Description | + | :----------------------- | :------------------------------------------------------------------------------------- | + | `NotApplicable` | Default value, should not occur in practice. | + | `ShopOnly` | Item can only be purchased in the Roblox catalog shop. | + | `MyExperiencesOnly` | Item can only be purchased in the creator's experiences. | + | `ShopAndMyExperiences` | Item can be purchased in the Roblox catalog shop or the creator's experiences. | + | `ExperiencesById` | Item can only be purchased in a specific list of experiences. | + | `ShopAndAllExperiences` | Item can be purchased in the Roblox catalog shop and all experiences. | + | `ExperiencesDevApiOnly` | Item can only be purchased in experiences via developer APIs. | + | `ShopAndExperiencesById` | Item can be purchased in the Roblox catalog shop or a whitelisted list of experiences. | + + ##### itemRestrictions Values + + | itemRestrictions | Limited or Unlimited | + | :--------------: | :-------------------: | + | `empty` | Unlimited | + | `Collectible` | UGC Limited | + | `Limited` | Roblox Limited | + | `LimitedUnique` | Roblox Limited Unique | code_samples: [] inherits: - Instance @@ -241,8 +562,10 @@ methods: Gets the item details for a list of items at once. description: | Gets the item details for a list of items at once. More efficient than - `AvatarEditorService:GetItemDetailsAsync` if you need to get all the item - details of a list. + `Class.AvatarEditorService:GetItemDetailsAsync()` if you need to get the + item details for multiple items. + + Returns an array of items (see Item Details Response above in summary). code_samples: [] parameters: - name: itemIds @@ -258,35 +581,7 @@ methods: returns: - type: Array summary: | - Returns an array of item details with the following fields: - - ```lua - { - "AssetType" = "string", - "CreatorName" = "string", - "CreatorTargetId" = 0, - "CreatorType" = "string", - "Description" = "string", - "FavoriteCount" = 0, - "Genres" = [ - "All" - ], - "Id" = 0, - "ItemRestrictions" = [ - "Limited" - ], - "ItemStatus": [ - "New" - ], - "ItemType" = "string", - "LowestPrice" = 0, - "Name" = "string", - "Price" = 0, - "ProductId" = 0 - } - ``` - - . + Returns an array of item details. tags: - Yields deprecation_message: '' @@ -312,35 +607,9 @@ methods: returns: - type: Array summary: | - Returns an array of item details with the following fields: - - ```lua - { - "AssetType" = "string", - "CreatorName" = "string", - "CreatorTargetId" = 0, - "CreatorType" = "string", - "Description" = "string", - "FavoriteCount" = 0, - "Genres" = [ - "All" - ], - "Id" = 0, - "ItemRestrictions" = [ - "Limited" - ], - "ItemStatus": [ - "New" - ], - "ItemType" = "string", - "LowestPrice" = 0, - "Name" = "string", - "Price" = 0, - "ProductId" = 0 - } - ``` - - . + Returns an array of item details. See + `Class.AvatarEditorService:GetBatchItemDetailsAsync()` for the + response format. tags: - Yields - Deprecated @@ -474,63 +743,41 @@ methods: parameters - the first indicating the ID of the item being retrieved and the second indicating its `Enum.AvatarItemType`. - Data returned in the format: + The response includes all fields from Item Details Response (see above in + summary), plus the following additional fields specific to single-item + queries: - ```lua - { - "IsForRent": true, - "ExpectedSellerId": 0, - "Owned": true, - "IsPurchasable": true, - "Id": 0, - "ItemType": "Asset", - "AssetType": "Image", - "BundleType": "BodyParts", - "Name": "string", - "Description": "string", - "ProductId": 0, - "Genres": [ - "All" - ], - "BundledItems": [ - { - "Owned": true, - "Id": 0, - "Name": "string", - "Type": "string" - } - ], - "ItemStatus": [ - "New" - ], - "ItemRestrictions": [ - "ThirteenPlus" - ], - "CreatorType": "User", - "CreatorTargetId": 0, - "CreatorName": "string", - "Price": 0, - "PremiumPricing": { - "PremiumDiscountPercentage": 0, - "PremiumPriceInRobux": 0 - }, - "LowestPrice": 0, - "PriceStatus": "string", - "UnitsAvailableForConsumption": 0, - "PurchaseCount": 0, - "FavoriteCount": 0 - } - ``` - -

To query for limited or unlimited assets, use the following - `itemRestrictions` values: - - | itemRestrictions | Limited or Unlimited | - | :--------------: | :-------------------: | - | `empty` | Unlimited | - | `Collectible` | UGC Limited | - | `Limited` | Roblox Limited | - | `LimitedUnique` | Roblox Limited Unique | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
OwnedbooleanWhether the item is owned by the current user.
IsPurchasablebooleanWhether the item can be purchased by the current user.
ExpectedSellerIdnumberThe user ID of the lowest private seller if resellable, or the creator's target ID otherwise. Used when calling purchase APIs.
CreatingUniverseIdnumberIf this asset was created in an experience, this is the universe ID where it was created. nil if not an in-experience creation.
code_samples: [] parameters: - name: itemId @@ -547,8 +794,7 @@ methods: returns: - type: Dictionary summary: | - A table containing the item info for the retrieved item. See above for - a sample table. + A table containing the item info for the retrieved item. tags: - Yields deprecation_message: '' @@ -781,12 +1027,12 @@ methods: "AssetId": 0, "Name": "string", "Price": 0, - "PremiumPrice": 0, + "PremiumPrice": 0 }, "Creator": { "CreatorId": 0, "CreatorType": "string", - "Name": "string", + "Name": "string" }, "Product": { "Id": 0, @@ -1139,51 +1385,8 @@ methods: This function returns a `Class.CatalogPages` object containing the result of the given search. - The returned data has the format: - - ```lua - [ - { - "Id": 0, - "ItemType": "Asset", - "AssetType": "Image", - "BundleType": "BodyParts", - "Name": "string", - "Description": "string", - "ProductId": 0, - "Genres": [ - "All" - ], - "BundledItems": [ - { - "Owned": true, - "Id": 0, - "Name": "string", - "Type": "string" - } - ], - "ItemStatus": [ - "New" - ], - "ItemRestrictions": [ - "ThirteenPlus" - ], - "CreatorType": "User", - "CreatorTargetId": 0, - "CreatorName": "string", - "Price": 0, - "PremiumPricing": { - "PremiumDiscountPercentage": 0, - "PremiumPriceInRobux": 0 - }, - "LowestPrice": 0, - "PriceStatus": "string", - "UnitsAvailableForConsumption": 0, - "PurchaseCount": 0, - "FavoriteCount": 0 - } - ] - ``` + Each item in the returned pages uses the Item Details Response format (see + above in summary). code_samples: [] parameters: - name: searchParameters @@ -1193,7 +1396,8 @@ methods: An object containing the parameters used for the search. returns: - type: CatalogPages - summary: '' + summary: | + A `Class.CatalogPages` object containing the search results. tags: - Yields deprecation_message: '' diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/CaptureService.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/CaptureService.yaml index 679b490c..d864f904 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/CaptureService.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/CaptureService.yaml @@ -224,7 +224,7 @@ methods: An array of `Enum.CaptureType`. - name: readFromAllEligibleExperiences type: boolean - default: + default: false summary: | A boolean; default is `false`. returns: diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/GenerationService.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/GenerationService.yaml index e08bc9b8..2754eb9b 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/GenerationService.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/GenerationService.yaml @@ -10,50 +10,9 @@ summary: | description: | `GenerationService` enables you to generate 3D objects from text prompts using Roblox's Cube 3D foundation model. This enables the generation of objects like - environmental props in-experience. - - You can control the output by providing an optional `Datatype.Vector3` to the - `SuggestedSize` parameter. Rather than simply rescaling the result, this - parameter guides the model during the creation process, influencing it to - create a mesh that attempts to match the proportions and size of your - specified bounding box. - - Mesh generation is a two step process: - - 1. `Class.GenerationService:GenerateMeshAsync()|GenerateMeshAsync()` starts - the mesh generation process using a text prompt and other required - parameters. It returns a unique identifier (generation ID) that can be used - to retrieve the future result. - 2. `Class.GenerationService:LoadGeneratedMeshAsync()|LoadGeneratedMeshAsync()` - loads the generated mesh into the experience. The mesh is returned as a - `Class.MeshPart` or `Class.Model`. - - Currently, `GenerationService` only supports the following usage: - - - `Class.GenerationService:GenerateMeshAsync()|GenerateMeshAsync()` must be - called from server scripts. - - `Class.GenerationService:LoadGeneratedMeshAsync()|LoadGeneratedMeshAsync()` - must be called from client scripts. - - As a result, when a mesh generation request originates from a client, the - client must send a signal to the server to initiate generation. Once the - server determines that generation is complete, it should notify the - appropriate client to call - `Class.GenerationService:LoadGeneratedMeshAsync()|LoadGeneratedMeshAsync()` - and retrieve the mesh. Note that since the generated mesh is loaded with - `Class.EditableMesh` content and only on the client, it is not replicated to - any other clients. - - See - [this demo experience](https://www.roblox.com/games/108838517877898/SuggestedSize-Generation-Template) - for a more detailed example including usage of the `SuggestedSize` option - (click the **⋯** button and **Edit in Studio**). -code_samples: - - GenerationService-ServerSideMeshGeneration - - GenerationService-ClientSideMeshGeneration - - GenerationService-ServerSideMeshGeneration-WithSuggestedSize - - GenerationService-ClientSideMeshGeneration-WithSuggestedSize - - GenerationService-StarterPlayerScripts-WithSuggestedSize + environmental props in-experience, as well as fully functional models like + vehicles that drive, planes that fly, and weapons that shoot. +code_samples: [] inherits: - Instance descendants: [] @@ -69,16 +28,18 @@ methods: unique IDs used to track and retrieve the result. description: | Starts the generation of a new 3D mesh from a text prompt and returns - unique IDs used to track and retrieve the result. You can optionally - receive intermediate results, such as the untextured mesh, by providing an - `intermediateResultCallback` function. After the generation is complete, - use + unique IDs used to track and retrieve the result. Must be called from + server scripts. You can optionally receive intermediate results, such as + the untextured mesh, by providing an `intermediateResultCallback` + function. + + After the generation is complete, use `Class.GenerationService:LoadGeneratedMeshAsync|LoadGeneratedMeshAsync()` to load and display the generated mesh. - **Error Codes** + #### Error Codes - | Error | Description | Recommended developer action | + | Error | Description | Recommended action | | ------------------------------------------ | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | | Rate limit exceeded | The maximum number of mesh generations has been exceeded for the minute. | Wait until the rate limit resets. | | Moderation failed | The mesh generation was flagged for moderation. | Review and modify the prompt to ensure it adheres to Roblox's moderation guidelines. | @@ -105,11 +66,11 @@ methods: default: summary: | A dictionary for additional generation options to influence the - result. The following key is supported: - `SuggestedSize` — Optional - `Datatype.Vector3` representing a size guide for the generated asset. - The service will attempt to create a model with a size and proportion - similar to the provided `Datatype.Vector3`. This does not guarantee - the final output size. + result. The optional `SuggestedSize` key (`Datatype.Vector3`) + represents a size guide for the generated asset, meaning + `GenerationService` will attempt to create a model with a size and + proportion similar to the provided `Datatype.Vector3`, although there + is no guarantee on the final output size. - name: intermediateResultCallback type: Function? default: @@ -123,31 +84,70 @@ methods: of `GenerateMeshAsync()`) and context ID (not currently used). tags: - Yields - deprecation_message: '' + deprecation_message: | + This method is scheduled for future deprecation. Explore + `Class.GenerationService:GenerateModelAsync()|GenerateModelAsync()` as a + newer method. security: None thread_safety: Unsafe capabilities: - DynamicGeneration - name: GenerationService:GenerateModelAsync - summary: '' - description: '' - code_samples: [] + summary: | + Enables generation of multi-mesh geometries according to provided `inputs` + and a `schema`. + description: | + Enables generation of multi-mesh geometries according to provided `inputs` + and a `schema`. + + This method throws an error during the generation process for issues like + prompt rejection, generation timeouts, `schema` mismatches, or backend + service errors. It's recommended to wrap it in a + `Global.LuaGlobals.pcall()` to catch such errors. + + See [this guide](../../../parts/model-generation.md) for more detailed + examples including usage of a `Behaviors` module to connect functional + behaviors to generated models. + code_samples: + - GenerationService-Basic-Car5 parameters: - name: inputs type: Dictionary default: - summary: '' + summary: | + A table representing conditioning inputs with the following keys: + + - `TextPrompt` — String description of the object to generate. + - `Size` — Optional `Datatype.Vector3` describing the object size to + generate. This is only approximate; scale the model extents + post‑generation if you need a specific size. + - `MaxTriangles` — Optional integer describing the maximum number of + triangles that the returned model will contain. Lower values result + in more faceted and low-poly generations. + - `GenerateTextures` — `true` (default) textures the resulting + generation, while `false` will not generate textures. - name: schema type: Dictionary default: - summary: '' + summary: | + Table representing the generation schema. Must contain a + `PredefinedSchema` key with a string value; current valid options are + `Car5` for a basic vehicle chassis consisting of five + `Class.Model|Models`, or `Body1` which results in a single mesh + output. - name: options type: Dictionary? default: - summary: '' + summary: | + Currently not used; reserved for future customization options. returns: - type: Tuple - summary: '' + summary: | + Tuple with the following elements: + + - A standard `Class.Model` container instance that is compliant with + the specified `schema`. + - A table containing a UUID and other metadata about the generation. tags: - Yields deprecation_message: '' @@ -163,10 +163,11 @@ methods: description: | Retrieves and loads a mesh generated by `Class.GenerationService:GenerateMeshAsync()|GenerateMeshAsync()` using - the provided `generationId`. The mesh can be returned as a - `Class.MeshPart` or `Class.Model`. Because editable meshes are not - replicated, the loaded mesh is not replicated to any other clients and can - only be loaded once per `generationId`. + the provided `generationId`. Must be called from client scripts. + + The mesh can be returned as a `Class.MeshPart` or `Class.Model`. Because + editable meshes are not replicated, the loaded mesh is not replicated to + any other clients and can only be loaded once per `generationId`. code_samples: [] parameters: - name: generationId diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/HttpService.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/HttpService.yaml index 0926001d..58241c29 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/HttpService.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/HttpService.yaml @@ -300,8 +300,9 @@ methods: JSON. This may cause problems if you want to use the outputted JSON elsewhere. - This method also accepts `Library.buffer|buffers`, which it encodes to - base64 (and often compresses) before converting to a JSON object. + This method also accepts `Library.buffer|buffers` up to 50 MiB, which it + encodes to base64 (and often compresses) before converting to a JSON + object. To reverse the encoding process and decode a JSON object, use the `Class.HttpService:JSONDecode()` method. @@ -430,6 +431,12 @@ methods: no An optional compression field that will compress the data in the request. The value can either be Enum.HttpCompression.None or Enum.HttpCompression.Gzip. + + Timeout + Integer + no + An optional timeout value in seconds to make requests time out more quickly. Values must be greater than zero and no greater than the default request timeout. This can be useful when debugging hanging requests. + diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/InputBinding.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/InputBinding.yaml index 7a1bb3f9..c866ebf1 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/InputBinding.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/InputBinding.yaml @@ -5,9 +5,8 @@ name: InputBinding type: class memory_category: Instances -summary: | - Defines which hardware binding should trigger the parent `Class.InputAction`. -description: | +summary: Defines which hardware binding should trigger the parent `Class.InputAction`. +description: |- An `InputBinding` defines which hardware binding should trigger the parent `Class.InputAction`, for example a key press, gamepad button, or tap on a touch‑enabled device. There can be multiple `InputBinding` instances parented @@ -20,10 +19,10 @@ tags: [] deprecation_message: '' properties: - name: InputBinding.Backward - summary: | + summary: |- Specifies an alternate `Enum.KeyCode` for dispatching directionally "backward" inputs to the parent `Class.InputAction`. - description: | + description: |- Specifies an alternate `Enum.KeyCode` for dispatching directionally "backward" inputs to `Class.InputAction:GetState()|GetState()` and the `Class.InputAction.StateChanged|StateChanged` event of the parent @@ -46,10 +45,10 @@ properties: capabilities: - Input - name: InputBinding.Down - summary: | + summary: |- Specifies an alternate `Enum.KeyCode` for dispatching directionally "down" inputs to the parent `Class.InputAction`. - description: | + description: |- Specifies an alternate `Enum.KeyCode` for dispatching directionally "down" inputs to `Class.InputAction:GetState()|GetState()` and the `Class.InputAction.StateChanged|StateChanged` event of the parent @@ -86,10 +85,10 @@ properties: capabilities: - Input - name: InputBinding.Forward - summary: | + summary: |- Specifies an alternate `Enum.KeyCode` for dispatching directionally "forward" inputs to the parent `Class.InputAction`. - description: | + description: |- Specifies an alternate `Enum.KeyCode` for dispatching directionally "forward" inputs to `Class.InputAction:GetState()|GetState()` and the `Class.InputAction.StateChanged|StateChanged` event of the parent @@ -112,10 +111,10 @@ properties: capabilities: - Input - name: InputBinding.KeyCode - summary: | + summary: |- Specifies the `Enum.KeyCode` which triggers the parent `Class.InputAction`. - description: | + description: |- Specifies the `Enum.KeyCode` which triggers the parent `Class.InputAction`. The code type should match the input action's `Class.InputAction.Type|Type`, for example `Enum.KeyCode.E` for an action @@ -139,10 +138,10 @@ properties: capabilities: - Input - name: InputBinding.Left - summary: | + summary: |- Specifies an alternate `Enum.KeyCode` for dispatching directionally "left" inputs to the parent `Class.InputAction`. - description: | + description: |- Specifies an alternate `Enum.KeyCode` for dispatching directionally "left" inputs to `Class.InputAction:GetState()|GetState()` and the `Class.InputAction.StateChanged|StateChanged` event of the parent @@ -175,10 +174,10 @@ properties: capabilities: - Input - name: InputBinding.PressedThreshold - summary: | + summary: |- Numerical value above which to fire an `Class.InputAction` with a `Class.InputAction.Type|Type` of `Enum.InputActionType|Bool`. - description: | + description: |- Numerical value above which to fire an `Class.InputAction` with a `Class.InputAction.Type|Type` of `Enum.InputActionType|Bool`, for example when a gamepad trigger such as `Enum.KeyCode.ButtonL2` exceeds `0.5` @@ -201,11 +200,37 @@ properties: can_save: true capabilities: - Input + - name: InputBinding.PrimaryModifier + summary: Specifies a primary `Enum.KeyCode` that must be pressed for the binding to activate. + description: |- + Specifies a `Enum.KeyCode` that serves as a required modifier for the binding. The `Class.InputBinding` + will only trigger the parent `Class.InputAction` if this input is pressed prior to + `Class.InputBinding.KeyCode|KeyCode`, `Class.InputBinding.UIButton|UIButton`, or composite directions. + + There is no ordering requirement between `Class.InputBinding.PrimaryModifier|PrimaryModifier` and + `Class.InputBinding.SecondaryModifier|SecondaryModifier`. If both properties are set, both modifiers + must be pressed to activate the binding, but the order in which they are pressed does not matter. + + If set to `Enum.KeyCode.Unknown`, no primary modifier is required. + code_samples: [] + type: KeyCode + tags: [] + deprecation_message: '' + security: + read: None + write: None + thread_safety: ReadSafe + category: Behavior + serialization: + can_load: true + can_save: true + capabilities: + - Input - name: InputBinding.ReleasedThreshold - summary: | + summary: |- Numerical value below which to fire an `Class.InputAction` with a `Class.InputAction.Type|Type` of `Enum.InputActionType|Bool`. - description: | + description: |- Numerical value below which to fire an `Class.InputAction` with a `Class.InputAction.Type|Type` of `Enum.InputActionType|Bool`, for example when a gamepad trigger such as `Enum.KeyCode.ButtonL2` falls below `0.5` @@ -229,22 +254,18 @@ properties: capabilities: - Input - name: InputBinding.ResponseCurve - summary: | - Numerical value to configure scaling for more precise thumbstick aiming. - description: | - A numerical value to control the sensitivity of gamepad thumbstick input - by applying a quadratic response curve. Commonly used for camera control - to make small thumbstick inputs more precise, while ramping up quickly to - allow for large movements with higher magnitude input. + summary: Numerical value to configure scaling for more precise thumbstick aiming. + description: |- + A numerical value to control the sensitivity of gamepad thumbstick input by applying + a quadratic response curve. Commonly used for camera control to make small thumbstick inputs more + precise, while ramping up quickly to allow for large movements with higher magnitude input. - Ranges between `1` to `10`, with higher values providing a more intense - curve. Default is `1`, at which input is returned exactly as received. + Ranges between `1` to `10`, with higher values providing a more intense curve. + Default is `1`, at which input is returned exactly as received. Only applicable when the parent action's `Class.InputAction.Type|Type` is - `Enum.InputActionType|Direction2D` and the - `Class.InputBinding.KeyCode|KeyCode` is - `Enum.KeyCode.Thumbstick1|Thumbstick1` or - `Enum.KeyCode.Thumbstick2|Thumbstick2`. + `Enum.InputActionType|Direction2D` and the `Class.InputBinding.KeyCode|KeyCode` + is `Enum.KeyCode.Thumbstick1|Thumbstick1` or `Enum.KeyCode.Thumbstick2|Thumbstick2`. code_samples: [] type: float tags: [] @@ -260,10 +281,10 @@ properties: capabilities: - Input - name: InputBinding.Right - summary: | + summary: |- Specifies an alternate `Enum.KeyCode` for dispatching directionally "right" inputs to the parent `Class.InputAction`. - description: | + description: |- Specifies an alternate `Enum.KeyCode` for dispatching directionally "right" inputs to `Class.InputAction:GetState()|GetState()` and the `Class.InputAction.StateChanged|StateChanged` event of the parent @@ -296,10 +317,10 @@ properties: capabilities: - Input - name: InputBinding.Scale - summary: | + summary: |- Amount by which to linearly scale the values of a directional `Class.InputAction`. - description: | + description: |- Amount by which to linearly scale the values of an `Class.InputAction` with `Class.InputAction.Type|Type` of `Enum.InputActionType|Direction1D`, `Enum.InputActionType|Direction2D`, or `Enum.InputActionType|Direction3D`. @@ -317,11 +338,35 @@ properties: can_save: true capabilities: - Input + - name: InputBinding.SecondaryModifier + summary: Specifies a secondary `Enum.KeyCode` that must be pressed for the binding to activate. + description: |- + Specifies a `Enum.KeyCode` that serves as a required modifier for the binding. The `Class.InputBinding` + will only trigger the parent `Class.InputAction` if this input is pressed prior to + `Class.InputBinding.KeyCode|KeyCode`, `Class.InputBinding.UIButton|UIButton`, or composite directions. + + There is no ordering requirement between `Class.InputBinding.PrimaryModifier|PrimaryModifier` and + `Class.InputBinding.SecondaryModifier|SecondaryModifier`. If both properties are set, both modifiers + must be pressed to activate the binding, but the order in which they are pressed does not matter. + + If set to `Enum.KeyCode.Unknown`, no secondary modifier is required. + code_samples: [] + type: KeyCode + tags: [] + deprecation_message: '' + security: + read: None + write: None + thread_safety: ReadSafe + category: Behavior + serialization: + can_load: true + can_save: true + capabilities: + - Input - name: InputBinding.UIButton - summary: | - Connects a `Class.GuiButton` to a boolean action. - description: | - `Class.GuiButton` to connect to a boolean action. + summary: Connects a `Class.GuiButton` to a boolean action. + description: '`Class.GuiButton` to connect to a boolean action.' code_samples: [] type: GuiButton tags: [] @@ -337,10 +382,10 @@ properties: capabilities: - Input - name: InputBinding.Up - summary: | + summary: |- Specifies an alternate `Enum.KeyCode` for dispatching directionally "up" inputs to the parent `Class.InputAction`. - description: | + description: |- Specifies an alternate `Enum.KeyCode` for dispatching directionally "up" inputs to `Class.InputAction:GetState()|GetState()` and the `Class.InputAction.StateChanged|StateChanged` event of the parent @@ -377,10 +422,10 @@ properties: capabilities: - Input - name: InputBinding.Vector2Scale - summary: | + summary: |- Amount by which to linearly scale the values of a two-directional `Class.InputAction`. - description: | + description: |- Amount by which to linearly scale the values of an `Class.InputAction` with `Class.InputAction.Type|Type` of `Enum.InputActionType|Direction2D`. code_samples: [] diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/Instance.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/Instance.yaml index f66f1a3d..abd87c3d 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/Instance.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/Instance.yaml @@ -920,7 +920,7 @@ methods: summary: | The `Class.Instance.Name` to be looked for. returns: - - type: Instance + - type: Instance? summary: | The `Class.Instance` found. tags: [] @@ -960,7 +960,7 @@ methods: summary: | The `Class.Object.ClassName` to be looked for. returns: - - type: Instance + - type: Instance? summary: | The `Class.Instance` found. tags: [] @@ -1006,7 +1006,7 @@ methods: summary: | The `Class.Object.ClassName` to be looked for. returns: - - type: Instance + - type: Instance? summary: | The `Class.Instance` found. tags: [] @@ -1095,7 +1095,7 @@ methods: summary: | Whether or not the search should be conducted recursively. returns: - - type: Instance + - type: Instance? summary: | The `Class.Instance` found. tags: [] @@ -1146,7 +1146,7 @@ methods: summary: | The `Class.Object.ClassName` to be looked for. returns: - - type: Instance + - type: Instance? summary: | The `Class.Instance` found. tags: [] @@ -1198,7 +1198,7 @@ methods: summary: | Whether or not the search should be conducted recursively. returns: - - type: Instance + - type: Instance? summary: | The `Class.Instance` found. tags: [] @@ -1223,7 +1223,7 @@ methods: summary: | The `Class.Instance.Name` to search for. returns: - - type: Instance + - type: Instance? summary: | The `Class.Instance` found. tags: [] diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/InstanceFileSyncService.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/InstanceFileSyncService.yaml index 72375a05..9fc17a0c 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/InstanceFileSyncService.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/InstanceFileSyncService.yaml @@ -78,7 +78,7 @@ methods: summary: | The absolute path to the file. returns: - - type: Instance + - type: Instance? summary: | Returns the Instance being synced to the file path, if one exists. Otherwise, returns nil. diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/Player.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/Player.yaml index 87cb90e8..9014cb08 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/Player.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/Player.yaml @@ -1260,7 +1260,7 @@ methods: - Deprecated deprecation_message: | This method has been superseded by - `Class.Player.GetFriendsOnline|GetFriendsOnline()`. + `Class.Player:GetFriendsOnlineAsync()|GetFriendsOnlineAsync()`. security: None thread_safety: Unsafe capabilities: diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/ReflectionService.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/ReflectionService.yaml index 400ac031..ff0ff5a2 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/ReflectionService.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/ReflectionService.yaml @@ -10,8 +10,8 @@ description: | `ReflectionService` allows scripts to query the engine for details about its API, including required security permissions, functionality, and inheritance structure. You can use this service to dynamically inspect classes and their - properties, which can be useful for debugging, tooling, or creating dynamic - behaviors based on the engine's capabilities. + properties, methods, and events, which can be useful for debugging, tooling, + or creating dynamic behaviors based on the engine's capabilities. The following is an example script that inspects classes and their properties: @@ -65,11 +65,11 @@ methods: ```lua { - -- The security context to use. Can be more expansive than the current script's security. + -- The security context to use; can be more expansive than the current script's security Security: SecurityCapabilities?, -- default: SecurityCapabilities.fromCurrent() - -- Require classes to derive from the passed-in class name. + -- Require classes to derive from the passed-in class name IsA: string?, -- default: nil - -- Whether to exclude Studio display information about the class. + -- Whether to exclude Studio display information about the class ExcludeDisplay: boolean?, -- default: false } ``` @@ -79,24 +79,26 @@ methods: ```lua { - -- The name of the class. + -- The name of the class Name: string, - -- The class's parent in the instance hierarchy (unless it's the root). + -- Whether the class is serialized (able to be saved to disk) + Serialized: boolean, + -- The class's parent in the instance hierarchy (unless it's the root) Superclass: string?, - -- The names of the class's direct children in the instance hierarchy. + -- The names of the class's direct children in the instance hierarchy Subclasses: {string}, - -- Studio display information. + -- Studio display information Display: { - -- Always "General" for classes. + -- Always "General" for classes Category: string, - -- A message indicating that the class is deprecated, if applicable. + -- A message indicating that the class is deprecated, if applicable DeprecationMessage: string?, }?, - -- The security permissions required to access this class. + -- The security permissions required to access this class Permits: { - -- If the class is a Service, the security capabilities required to obtain access. If not applicable, this field isn't present. + -- If the class is a Service, the security capabilities required to obtain access. If not applicable, this field isn't present GetService: SecurityCapabilities?, - -- The security capabilities required to create an instance of this class. If not possible, this field isn't present. + -- The security capabilities required to create an instance of this class. If not possible, this field isn't present New: SecurityCapabilities?, } } @@ -137,11 +139,11 @@ methods: ```lua { - -- The security context to use. Can be more expansive than the current script's security. + -- The security context to use; can be more expansive than the current script's security Security: SecurityCapabilities?, -- default: SecurityCapabilities.fromCurrent() - -- Require classes to derive from the passed-in class name. + -- Require classes to derive from the passed-in class name IsA: string?, -- default: nil - -- Whether to exclude Studio display information about the classes. + -- Whether to exclude Studio display information about the classes ExcludeDisplay: boolean?, -- default: false } ``` @@ -182,11 +184,11 @@ methods: ```lua { - -- The security context to use. Can be more expansive than the current script's security. + -- The security context to use; can be more expansive than the current script's security Security: SecurityCapabilities?, -- default: SecurityCapabilities.fromCurrent() - -- Whether to exclude inherited properties from superclasses. + -- Whether to exclude inherited properties from superclasses ExcludeInherited: boolean?, -- default: false - -- Whether to exclude Studio display information about the properties. + -- Whether to exclude Studio display information about the properties ExcludeDisplay: boolean?, -- default: false } ``` @@ -197,32 +199,32 @@ methods: ```lua { - -- The name of the property. + -- The name of the property Name: string, - -- Whether the property is serialized (able to be saved to disk or sent over the network). + -- The superclass from which the property is inherited, or the class name if not inherited + Owner: string, + -- Whether the property is serialized (able to be saved to disk or sent over the network) Serialized: boolean, - -- The type of the property. + -- The type of the property Type: ReflectionType, - -- The content type of the property, if applicable. + -- The content type of the property, if applicable ContentType: Enum.AssetType?, - -- Studio display information. + -- Studio display information Display: { - -- The category under which the property is listed in Studio. + -- The category under which the property is listed in Studio Category: string, - -- A message indicating that the property is deprecated, if applicable. + -- A message indicating that the property is deprecated, if applicable DeprecationMessage: string?, - -- The order in which the property appears in Studio. - LayoutOrder: number, }?, - -- The security permissions required to access this property. + -- The security permissions required to access this property Permits: { - -- The security context required to read this property. + -- The security context required to read this property Read: SecurityCapabilities?, - -- The security context required to read this property while thread-safe. + -- The security context required to read this property while thread-safe ReadParallel: SecurityCapabilities?, - -- The security context required to write to this property. + -- The security context required to write to this property Write: SecurityCapabilities?, - -- The security context required to write to this property while thread-safe. + -- The security context required to write to this property while thread-safe WriteParallel: SecurityCapabilities?, }, } @@ -251,5 +253,167 @@ methods: security: None thread_safety: Unsafe capabilities: [] + - name: ReflectionService:GetMethodsOfClass + summary: | + Returns a list of methods for a given class with filters applied. + description: | + Given a class name in the Roblox API, returns a list of `ReflectedMethod` + dictionaries for all methods of that class that match the provided filter + criteria. If no such class name exists, returns `nil`. + + If you pass in a `ReflectionMemberFilter` dictionary, you can adjust the + set of eligible methods and adjust the output behavior: + + ```lua + { + -- The security context to use; can be more expansive than the current script's security + Security: SecurityCapabilities?, -- default: SecurityCapabilities.fromCurrent() + -- Whether to exclude inherited methods from superclasses + ExcludeInherited: boolean?, -- default: false + -- Whether to exclude Studio display information about the methods + ExcludeDisplay: boolean?, -- default: false + } + ``` + + If the class name is valid and that class has methods, you'll get a list + of `ReflectedMethod` dictionaries as output, each with the following + structure: + + ```lua + { + -- The name of the method + Name: string, + -- The superclass from which the property is inherited, or the class name if not inherited + Owner: string, + -- A list of all parameters the method takes + Parameters: { + { + -- The name of the parameter + Name: string, + -- The type of the parameter + Type: ReflectionType, + -- The default value of the parameter, if it has one + DefaultValue: any?, + } + }, + -- The return type of the method; "void" if none + ReturnType: ReflectionType, + -- Whether the method is yielding + CanYield: boolean, + -- Studio display information + Display: { + -- A message indicating that the method is deprecated, if applicable + DeprecationMessage: string?, + }?, + -- The security permissions required to access this method + Permits: { + -- The security permissions required to call the method in a single-threaded context + Call: SecurityCapabilities?, + -- The security permissions required to call the method in a parallel context + CallParallel: SecurityCapabilities?, + }, + } + ``` + code_samples: [] + parameters: + - name: className + type: string + default: + summary: | + The name of the class for which you wish to retrieve methods. + - name: filter + type: Dictionary + default: nil + summary: | + An optional filter to restrict or expand the set of methods that this + method can return and change the method's behavior. + returns: + - type: Array + summary: | + A list of `ReflectedMethod` dictionaries with reflection information + for each method of the class that matches the filter criteria. + tags: + - CustomLuaState + deprecation_message: '' + security: None + thread_safety: Unsafe + capabilities: [] + - name: ReflectionService:GetEventsOfClass + summary: | + Returns a list of events for a given class with filters applied. + description: | + Given a class name in the Roblox API, returns a list of `ReflectedEvent` + dictionaries for all events of that class that match the provided filter + criteria. If no such class name exists, returns `nil`. + + If you pass in a `ReflectionMemberFilter` dictionary, you can adjust the + set of eligible events and adjust the output behavior: + + ```lua + { + -- The security context to use; can be more expansive than the current script's security + Security: SecurityCapabilities?, -- default: SecurityCapabilities.fromCurrent() + -- Whether to exclude inherited events from superclasses + ExcludeInherited: boolean?, -- default: false + -- Whether to exclude Studio display information about the events + ExcludeDisplay: boolean?, -- default: false + } + ``` + + If the class name is valid and that class has events, you'll get a list of + `ReflectedEvent` dictionaries as output, each with the following + structure: + + ```lua + { + -- The name of the event + Name: string, + -- The superclass from which the property is inherited, or the class name if not inherited + Owner: string, + -- A list of all parameters the event passes to connected functions + Parameters: { + { + -- The name of the parameter + Name: string, + -- The type of the parameter + Type: ReflectionType, + } + }, + -- Studio display information + Display: { + -- A message indicating that the event is deprecated, if applicable + DeprecationMessage: string?, + }?, + -- The security permissions required to access this event + Permits: { + -- The security permissions required to listen for the event in any context + Listen: SecurityCapabilities?, + }, + } + ``` + code_samples: [] + parameters: + - name: className + type: string + default: + summary: | + The name of the class for which you wish to retrieve events. + - name: filter + type: Dictionary + default: nil + summary: | + An optional filter to restrict or expand the set of events that this + method can return and change the method's behavior. + returns: + - type: Array + summary: | + A list of `ReflectedEvent` dictionaries with reflection information + for each event of the class that matches the filter criteria. + tags: + - CustomLuaState + deprecation_message: '' + security: None + thread_safety: Unsafe + capabilities: [] events: [] callbacks: [] diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/RotationCurve.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/RotationCurve.yaml index 18da1396..6169295f 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/RotationCurve.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/RotationCurve.yaml @@ -120,7 +120,7 @@ methods: summary: | Time at which to sample the curve. returns: - - type: CoordinateFrame? + - type: CFrame? summary: | Value of the curve at the requested `time`. tags: [] diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/Sound.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/Sound.yaml index fbcdda15..f5607c30 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/Sound.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/Sound.yaml @@ -49,26 +49,6 @@ properties: can_save: true capabilities: - LegacySound - - name: Sound.ChannelCount - summary: '' - description: '' - code_samples: [] - type: int - tags: - - ReadOnly - - NotReplicated - - NotBrowsable - deprecation_message: '' - security: - read: RobloxScriptSecurity - write: RobloxScriptSecurity - thread_safety: ReadSafe - category: Asset - serialization: - can_load: false - can_save: false - capabilities: - - LegacySound - name: Sound.EmitterSize summary: | The minimum distance, in studs, at which a 3D `Class.Sound` (direct child @@ -134,23 +114,6 @@ properties: can_save: false capabilities: - LegacySound - - name: Sound.IsMutedForCapture - summary: '' - description: '' - code_samples: [] - type: boolean - tags: [] - deprecation_message: '' - security: - read: RobloxScriptSecurity - write: RobloxScriptSecurity - thread_safety: ReadSafe - category: Data - serialization: - can_load: true - can_save: true - capabilities: - - LegacySound - name: Sound.IsPaused summary: | Read-only property which returns `true` when the `Class.Sound` is not diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/StarterPlayer.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/StarterPlayer.yaml index 0a43771c..1875d145 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/StarterPlayer.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/StarterPlayer.yaml @@ -108,7 +108,6 @@ properties: tags: - NotReplicated - NotScriptable - - NotBrowsable deprecation_message: '' security: read: None @@ -387,8 +386,7 @@ properties: description: '' code_samples: [] type: boolean - tags: - - NotBrowsable + tags: [] deprecation_message: '' security: read: None diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/SurfaceAppearance.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/SurfaceAppearance.yaml index abf250d1..d5c69cbf 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/SurfaceAppearance.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/SurfaceAppearance.yaml @@ -391,7 +391,7 @@ properties: tags: [] deprecation_message: '' security: - read: RobloxEngineSecurity + read: RobloxScriptSecurity write: RobloxEngineSecurity thread_safety: ReadSafe category: Appearance diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/TestService.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/TestService.yaml index fda595c4..291ffec9 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/TestService.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/TestService.yaml @@ -746,6 +746,10 @@ methods: type: string default: summary: '' + - name: source + type: Instance + default: + summary: '' returns: - type: () summary: '' diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/TextChatService.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/TextChatService.yaml index ddf19839..15c74d3f 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/TextChatService.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/TextChatService.yaml @@ -417,6 +417,74 @@ methods: thread_safety: Unsafe capabilities: - Chat + - name: TextChatService:GetChatGroupsAsync + summary: | + Returns chat group IDs that indicate which players can synchronously text + chat together. + description: | + Returns a sorted array of arrays of chat group IDs for the given players. + Each chat group ID is a string that represents a communication-compatible + group within the current universe. + + If two or more players share the same chat group ID, those players are + able to synchronously text chat with each other based on their age-check + status and chat settings. + + This method is server-side only and intended for real-time use cases such + as matchmaking and teleporting. Chat group IDs are unique to the current + universe, may change over time, and should not be stored once the user has + left the experience. While you can hold onto the data returned for the + purposes of gameplay while the user is in the experience, this data should + not be stored after they've left. + + To use this method, you must enable **Chat & Voice Groups APIs** in + **Experience Settings** ⟩ **Communication** in Roblox Studio and agree to + the Roblox Terms of Use. + + ```lua + local TextChatService = game:GetService("TextChatService") + local Players = game:GetService("Players") + local players = Players:GetPlayers() + + local success, chatGroups = pcall(function() + return TextChatService:GetChatGroupsAsync(players) + end) + + if not success then + warn("Failed to retrieve chat groups") + return + end + + for _, group in ipairs(chatGroups) do + -- Each group contains chat group ID strings. + -- Players who share a matching group ID can chat with each other. + for _, groupId in ipairs(group) do + print("Chat group ID:", groupId) + end + end + ``` + code_samples: + - TextChatService-Chat-Groups-Teleport + parameters: + - name: players + type: Instances + default: + summary: | + A list of `Class.Player|Players` currently in the experience to + evaluate for text chat compatibility. + returns: + - type: Array + summary: | + A sorted array of arrays of chat group ID strings. Players who share a + matching chat group ID are eligible to synchronously text chat with + each other. + tags: + - Yields + deprecation_message: '' + security: None + thread_safety: Unsafe + capabilities: + - Chat events: - name: TextChatService.BubbleDisplayed summary: | diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/VoiceChatService.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/VoiceChatService.yaml index 2bbcc2c4..657efbda 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/VoiceChatService.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/VoiceChatService.yaml @@ -115,6 +115,73 @@ properties: can_save: true capabilities: [] methods: + - name: VoiceChatService:GetChatGroupsAsync + summary: | + Returns chat group IDs that indicate which players can voice chat + together. + description: | + Returns a sorted array of arrays of chat group IDs for the given players. + Each chat group ID is a string that represents a communication-compatible + group within the current universe. + + If two or more players share the same chat group ID, those players are + eligible to voice chat with each other based on their age-check status, + voice chat eligibility, and communication settings. + + This method is server-side only and intended for real-time use cases such + as matchmaking and teleporting. Chat group IDs are unique to the current + universe, may change over time, and should not be stored once the user has + left the experience. While you can hold onto the data returned for the + purposes of gameplay while the user is in the experience, this data should + not be stored after they've left. + + To use this method, you must enable **Chat & Voice Groups APIs** in + **Experience Settings** ⟩ **Communication** in Roblox Studio and agree to + the Roblox Terms of Use. + + ```lua + local VoiceChatService = game:GetService("VoiceChatService") + local Players = game:GetService("Players") + local players = Players:GetPlayers() + + local success, chatGroups = pcall(function() + return VoiceChatService:GetChatGroupsAsync(players) + end) + + if not success then + warn("Failed to retrieve chat groups") + return + end + + for _, group in ipairs(chatGroups) do + -- Each group contains chat group ID strings. + -- Players who share a matching group ID can chat with each other. + for _, groupId in ipairs(group) do + print("Chat group ID:", groupId) + end + end + ``` + code_samples: + - VoiceChatService-Chat-Groups-Teleport + parameters: + - name: players + type: Instances + default: + summary: | + A list of `Class.Player|Players` currently in the experience to + evaluate for voice chat compatibility. + returns: + - type: Array + summary: | + A sorted array of arrays of chat group ID strings. Players who share a + matching chat group ID are eligible to voice chat with each other. + tags: + - Yields + deprecation_message: '' + security: None + thread_safety: Unsafe + capabilities: + - Chat - name: VoiceChatService:IsVoiceEnabledForUserIdAsync summary: | Returns whether or not the given user has voice enabled. diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/Workspace.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/Workspace.yaml index 3f206a88..7163824c 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/Workspace.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/Workspace.yaml @@ -239,7 +239,8 @@ properties: serialization: can_load: true can_save: true - capabilities: [] + capabilities: + - Basic - name: Workspace.DistributedGameTime summary: | The amount of time, in seconds, that the game has been running. @@ -352,7 +353,8 @@ properties: serialization: can_load: false can_save: false - capabilities: [] + capabilities: + - Basic - name: Workspace.FluidForces summary: | Determines whether the physics engine computes aerodynamic forces on @@ -400,7 +402,8 @@ properties: serialization: can_load: true can_save: true - capabilities: [] + capabilities: + - Basic - name: Workspace.Gravity summary: | Determines the acceleration due to gravity applied to falling @@ -424,7 +427,8 @@ properties: serialization: can_load: true can_save: true - capabilities: [] + capabilities: + - Basic - name: Workspace.IKControlConstraintSupport summary: | Enables support for constraints for IKControls. If disabled, IKControls @@ -1471,7 +1475,8 @@ methods: deprecation_message: '' security: None thread_safety: Unsafe - capabilities: [] + capabilities: + - Basic - name: Workspace:UnjoinFromOutsiders summary: | Breaks all joints between the specified `Class.BasePart|BaseParts` and diff --git a/.cursor/rules/roblox/en-us/reference/engine/classes/WrapDeformer.yaml b/.cursor/rules/roblox/en-us/reference/engine/classes/WrapDeformer.yaml index afbd0ed1..296bbdd6 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/classes/WrapDeformer.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/classes/WrapDeformer.yaml @@ -92,7 +92,7 @@ methods: default: summary: '' - name: cageOrigin - type: CoordinateFrame? + type: CFrame? default: summary: '' returns: diff --git a/.cursor/rules/roblox/en-us/reference/engine/enums/InstanceFileSyncStatus.yaml b/.cursor/rules/roblox/en-us/reference/engine/enums/InstanceFileSyncStatus.yaml index b1d1d9b0..47b2378c 100644 --- a/.cursor/rules/roblox/en-us/reference/engine/enums/InstanceFileSyncStatus.yaml +++ b/.cursor/rules/roblox/en-us/reference/engine/enums/InstanceFileSyncStatus.yaml @@ -37,3 +37,10 @@ items: value: 3 tags: [] deprecation_message: '' + - name: AncestorErrored + summary: | + The `Class.Instance` is not currently being synced because the root of its + sync tree is `Errored`. + value: 4 + tags: [] + deprecation_message: '' diff --git a/.cursor/rules/roblox/en-us/resources/feature-packages/index.md b/.cursor/rules/roblox/en-us/resources/feature-packages/index.md index 78adf548..136c54fb 100644 --- a/.cursor/rules/roblox/en-us/resources/feature-packages/index.md +++ b/.cursor/rules/roblox/en-us/resources/feature-packages/index.md @@ -34,7 +34,7 @@ The **Bundles** feature package offers out-of-the-box functionality to sell coll
- +
@@ -105,7 +105,7 @@ The **Missions** feature package offers out-of-the-box functionality to create m
- +
@@ -176,7 +176,7 @@ The **Season Passes** feature package offers out-of-the-box functionality to cre
- +
@@ -247,7 +247,7 @@ The **Engagement Rewards** feature package is a customizable framework for offer
- +
diff --git a/.cursor/rules/roblox/en-us/resources/modules/event-sequencer.md b/.cursor/rules/roblox/en-us/resources/modules/event-sequencer.md index ccb5c57e..f5b4f729 100644 --- a/.cursor/rules/roblox/en-us/resources/modules/event-sequencer.md +++ b/.cursor/rules/roblox/en-us/resources/modules/event-sequencer.md @@ -12,7 +12,7 @@ description: Event Sequencer is a powerful framework for building live, cross-se This framework has been battle tested in Roblox events like the [Twenty One Pilots](https://www.youtube.com/watch?v=0fAhhoXK12o) and [24kGoldn](https://www.youtube.com/watch?v=UfzqGkfRKr4) concerts, as well as many highly visited experiences.
- +
To see **EventSequencer** in action within an editable place, check out the [Concert](https://www.roblox.com/games/10275826693/Concert) template in Roblox Studio. This template is a comprehensive starting point for developers to create events/concerts and familiarize themselves with the various features and components involved. diff --git a/.cursor/rules/roblox/en-us/studio/index.md b/.cursor/rules/roblox/en-us/studio/index.md index 73b9bcfe..96d31d0b 100644 --- a/.cursor/rules/roblox/en-us/studio/index.md +++ b/.cursor/rules/roblox/en-us/studio/index.md @@ -175,7 +175,7 @@ export const sections = [ /> )} {content.video && ( - + )}

{content.title}

diff --git a/.cursor/rules/roblox/en-us/studio/optimization/memory-usage.md b/.cursor/rules/roblox/en-us/studio/optimization/memory-usage.md index 6ab7240e..fcd71ef6 100644 --- a/.cursor/rules/roblox/en-us/studio/optimization/memory-usage.md +++ b/.cursor/rules/roblox/en-us/studio/optimization/memory-usage.md @@ -7,7 +7,7 @@ import OpeningSteps from '../../includes/developer-console/opening-developer-con Every building and scripting component that you add to your experience consumes memory. When memory usage reaches engine limits, the user's device or server may crash, so you need to actively monitor usage. -
+
The **Developer Console** provides two tools for monitoring memory usage: diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/building/code-with-assistant.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/building/code-with-assistant.md index 86022d39..de1eeb5c 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/building/code-with-assistant.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/building/code-with-assistant.md @@ -6,7 +6,7 @@ prev: /tutorials/curriculums/building/work-with-parts ---
- +

**Assistant** is Roblox's AI helper that can help you create and code your experiences. In this chapter, let's walk through how to open Assistant in Studio, write requests that change part behavior, and playtest your results to see if you need to make any changes to the Assistant's code sample. diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/apply-polished-assets.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/apply-polished-assets.md index e071ecc5..f38cee21 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/apply-polished-assets.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/apply-polished-assets.md @@ -5,7 +5,7 @@ prev: /tutorials/curriculums/core/building/customize-global-lighting comments: The links to the Materials and PBR Modeling guides must be replaced by a single link to the Environmental Art curriculum once that is published. The link at the end should also be changed to link to the next sets of tutorials. --- - +
diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/create-an-environment-with-terrain.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/create-an-environment-with-terrain.md index b17b5bf6..6b74aaaa 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/create-an-environment-with-terrain.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/create-an-environment-with-terrain.md @@ -5,7 +5,7 @@ next: /tutorials/curriculums/core/building/greybox-a-playable-area prev: /tutorials/curriculums/core/building/create-a-project --- - +
diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/create-basic-visual-effects.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/create-basic-visual-effects.md index 53bebb74..59418197 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/create-basic-visual-effects.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/create-basic-visual-effects.md @@ -5,7 +5,7 @@ prev: /tutorials/curriculums/core/scripting/script-an-upgrade-button next: /tutorials/curriculums/core/building/customize-global-lighting --- - +
diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/customize-global-lighting.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/customize-global-lighting.md index 8906336f..f51af5d0 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/customize-global-lighting.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/customize-global-lighting.md @@ -5,7 +5,7 @@ prev: /tutorials/curriculums/core/building/create-basic-visual-effects next: /tutorials/curriculums/core/building/apply-polished-assets --- - +
**Global lighting** is the luminescence from either the sun or moon in your environment. By customizing a couple of key default properties in the `Class.Lighting` service and its default child objects in Studio, you can drastically change how global lighting looks and feels in your experience, as well as how the light interacts with any other object you place in the 3D space. diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/greybox-a-playable-area.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/greybox-a-playable-area.md index b561aaf5..f86f8455 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/greybox-a-playable-area.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/building/greybox-a-playable-area.md @@ -5,7 +5,7 @@ next: /tutorials/curriculums/core/scripting/script-game-behavior prev: /tutorials/curriculums/core/building/create-an-environment-with-terrain --- - +
diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/index.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/index.md index 449ac0f4..646f3d74 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/index.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/index.md @@ -15,7 +15,7 @@ hideInPageNavigation: true
- +
diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/scripting/create-player-hazards.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/scripting/create-player-hazards.md index 70499461..9dfb38c3 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/scripting/create-player-hazards.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/scripting/create-player-hazards.md @@ -9,7 +9,7 @@ prev: /tutorials/curriculums/core/scripting/record-and-display-player-data src="https://www.youtube-nocookie.com/embed/vlzZm3PQGfQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" -allowfullscreen> +allowFullScreen>
diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/scripting/record-and-display-player-data.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/scripting/record-and-display-player-data.md index 50aa3f75..5d62045b 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/scripting/record-and-display-player-data.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/scripting/record-and-display-player-data.md @@ -5,7 +5,7 @@ next: /tutorials/curriculums/core/scripting/create-player-hazards prev: /tutorials/curriculums/core/scripting/script-game-behavior --- - +
diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/scripting/script-an-upgrade-button.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/scripting/script-an-upgrade-button.md index 753fb208..ab1ec1bd 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/scripting/script-an-upgrade-button.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/scripting/script-an-upgrade-button.md @@ -5,7 +5,7 @@ prev: /tutorials/curriculums/core/scripting/create-player-hazards next: /tutorials/curriculums/core/building/create-basic-visual-effects --- - +
diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/scripting/script-game-behavior.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/scripting/script-game-behavior.md index e227be48..dfc37700 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/core/scripting/script-game-behavior.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/core/scripting/script-game-behavior.md @@ -5,7 +5,7 @@ next: /tutorials/curriculums/core/scripting/record-and-display-player-data prev: /tutorials/curriculums/core/building/greybox-a-playable-area --- - +
diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/curriculum-overview.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/curriculum-overview.md index 5f1cd0e4..e132a9f7 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/curriculum-overview.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/curriculum-overview.md @@ -4,7 +4,7 @@ description: An overview of creation curriculum paths covering topics like model hideInPageNavigation: true --- - +

@@ -47,7 +47,7 @@ Learn the foundational skills you need to become an environmental artist.
- +
@@ -118,7 +118,7 @@ Learn the programming skills you need to introduce gameplay to the laser tag env
- +
@@ -189,7 +189,7 @@ Learn the design skills you need to implement UI that informs players of the las
- +
diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/assemble-an-asset-library.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/assemble-an-asset-library.md index 5cb20331..0df3223b 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/assemble-an-asset-library.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/assemble-an-asset-library.md @@ -5,7 +5,7 @@ next: /tutorials/curriculums/environmental-art/construct-your-world prev: /tutorials/curriculums/environmental-art/develop-polished-assets --- - +
diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/construct-your-world.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/construct-your-world.md index bd4e2760..64ac990e 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/construct-your-world.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/construct-your-world.md @@ -5,7 +5,7 @@ next: /tutorials/curriculums/environmental-art/optimize-your-experience prev: /tutorials/curriculums/environmental-art/assemble-an-asset-library --- - +
diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/develop-polished-assets.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/develop-polished-assets.md index d487784c..a17ce61f 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/develop-polished-assets.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/develop-polished-assets.md @@ -5,7 +5,7 @@ next: /tutorials/curriculums/environmental-art/assemble-an-asset-library prev: /tutorials/curriculums/environmental-art/greybox-your-environment --- - +
diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/greybox-your-environment.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/greybox-your-environment.md index 71f54c9f..776b2892 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/greybox-your-environment.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/greybox-your-environment.md @@ -7,7 +7,7 @@ prev: /tutorials/curriculums/environmental-art/ import PlaytestModes from '../../../includes/studio/playtest-modes.md' - +
diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/index.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/index.md index 4a391a05..fcbb018e 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/index.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/index.md @@ -15,7 +15,7 @@ hideInPageNavigation: true
- +
diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/optimize-your-experience.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/optimize-your-experience.md index 9168c13c..dd392b1c 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/optimize-your-experience.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/environmental-art/optimize-your-experience.md @@ -4,7 +4,7 @@ description: Explains how to configure your assets and Studio settings to improv prev: /tutorials/curriculums/environmental-art/construct-your-world --- - +
diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/gameplay-scripting/index.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/gameplay-scripting/index.md index 7d8e2b6d..202fbc2d 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/gameplay-scripting/index.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/gameplay-scripting/index.md @@ -11,7 +11,7 @@ hideInPageNavigation: true
- +
diff --git a/.cursor/rules/roblox/en-us/tutorials/curriculums/user-interface-design/index.md b/.cursor/rules/roblox/en-us/tutorials/curriculums/user-interface-design/index.md index 3b146d5a..709ca67e 100644 --- a/.cursor/rules/roblox/en-us/tutorials/curriculums/user-interface-design/index.md +++ b/.cursor/rules/roblox/en-us/tutorials/curriculums/user-interface-design/index.md @@ -15,7 +15,7 @@ hideInPageNavigation: true
- +
diff --git a/.cursor/rules/roblox/en-us/tutorials/index.md b/.cursor/rules/roblox/en-us/tutorials/index.md index 4beb5bca..ebe3e2be 100644 --- a/.cursor/rules/roblox/en-us/tutorials/index.md +++ b/.cursor/rules/roblox/en-us/tutorials/index.md @@ -241,7 +241,7 @@ While many creators focus on a single area, the following tutorials walk you thr
- +
Environmental art Learn how to recreate a high-quality environment for a first-person laser tag experience. @@ -259,7 +259,7 @@ While many creators focus on a single area, the following tutorials walk you thr
- +
Gameplay scripting Learn how to organize and implement the gameplay logic for a large, complex project. @@ -277,7 +277,7 @@ While many creators focus on a single area, the following tutorials walk you thr
- +
UI design Learn how to design and implement UI components for unique user flows. diff --git a/.cursor/rules/roblox/en-us/tutorials/use-case-tutorials/input-and-camera/detect-user-input.md b/.cursor/rules/roblox/en-us/tutorials/use-case-tutorials/input-and-camera/detect-user-input.md index d71ae004..a584b32f 100644 --- a/.cursor/rules/roblox/en-us/tutorials/use-case-tutorials/input-and-camera/detect-user-input.md +++ b/.cursor/rules/roblox/en-us/tutorials/use-case-tutorials/input-and-camera/detect-user-input.md @@ -89,9 +89,9 @@ First, you'll need a function to handle when user input is detected. `Class.ContextActionService` can be used to **bind** a function to a specific input by using the `Class.ContextActionService:BindAction()|BindAction` function, which accepts several arguments: -- The name of the action -- The function to handle the action (also called a "callback") -- Whether or not a touchscreen button should be displayed +- The name of the action. +- The function to handle the action (also called a "callback"). +- Whether or not a touchscreen button should be displayed. - Any amount of `Enum.KeyCodes` to detect and associate with the action. KeyCodes are values that represent different input buttons, such as keyboard keys or controller buttons. A full list of codes is available `Enum.KeyCode|here`. diff --git a/.cursor/rules/roblox/en-us/tutorials/use-case-tutorials/use-case-tutorial-overview.md b/.cursor/rules/roblox/en-us/tutorials/use-case-tutorials/use-case-tutorial-overview.md index b7150729..092830bf 100644 --- a/.cursor/rules/roblox/en-us/tutorials/use-case-tutorials/use-case-tutorial-overview.md +++ b/.cursor/rules/roblox/en-us/tutorials/use-case-tutorials/use-case-tutorial-overview.md @@ -4,7 +4,7 @@ description: An overview of creation use case tutorials covering topics like mod hideInPageNavigation: true --- - + Modeling @@ -21,7 +21,7 @@ Use solid modeling operations directly in Studio to form complex shapes by union
- +
Intro to world building
@@ -456,7 +456,7 @@ Use third-party modeling tools like Blender to create meshes, then import them i
- +
Physics 101
diff --git a/.cursor/rules/roblox/en-us/ui/styling/editor.md b/.cursor/rules/roblox/en-us/ui/styling/editor.md index d7a0513f..6193816c 100644 --- a/.cursor/rules/roblox/en-us/ui/styling/editor.md +++ b/.cursor/rules/roblox/en-us/ui/styling/editor.md @@ -6,7 +6,7 @@ description: Explore the built-in Style Editor, a comprehensive tool that allows The built-in **Style Editor** is a comprehensive tool that allows you to create, manage, and apply UI styles for Roblox experiences through a combination of [tokens](#style-tokens), [design sheets](#design-sheets), [style rules](#style-rules), and [themes](#style-themes).
- +
Access the **Style Editor** via the **UI** tab. diff --git a/.cursor/rules/roblox/en-us/ui/ui-drag-detectors.md b/.cursor/rules/roblox/en-us/ui/ui-drag-detectors.md index d45b6896..ae975b42 100644 --- a/.cursor/rules/roblox/en-us/ui/ui-drag-detectors.md +++ b/.cursor/rules/roblox/en-us/ui/ui-drag-detectors.md @@ -224,7 +224,7 @@ The following slider designates its container as the `Class.UIDragDetector.Bound -To test this example, download the `TransparencySlider.rbxm` file, right‑click `Class.StarterGui` in the [Explorer](../studio/explorer.md) window, select **Insert from File**, and choose the downloaded file. +To test this example, download the `TransparencySlider.rbxm` file, right‑click `Class.StarterGui` in the [Explorer](../studio/explorer.md) window, select **Insert** ⟩ **Import Roblox Model**, and choose the downloaded file. ```lua title="UIDragDetector - Event Signal Transparency Change" @@ -265,7 +265,7 @@ The following detector has its `Class.UIDragDetector.DragStyle|DragStyle` set to -To test this example, download the `HueRotator.rbxm` file, right‑click `Class.StarterGui` in the [Explorer](../studio/explorer.md) window, select **Insert from File**, and choose the downloaded file. +To test this example, download the `HueRotator.rbxm` file, right‑click `Class.StarterGui` in the [Explorer](../studio/explorer.md) window, select **Insert** ⟩ **Import Roblox Model**, and choose the downloaded file. ```lua title="UIDragDetector - DragRotation Change" @@ -332,7 +332,7 @@ The following example utilizes a constraint function that clamps the planar drag -To test this example, download the `GridDrag.rbxm` file, right‑click `Class.StarterGui` in the [Explorer](../studio/explorer.md) window, select **Insert from File**, and choose the downloaded file. +To test this example, download the `GridDrag.rbxm` file, right‑click `Class.StarterGui` in the [Explorer](../studio/explorer.md) window, select **Insert** ⟩ **Import Roblox Model**, and choose the downloaded file. ```lua title="UIDragDetector - Drag in Grid, Snapping to Tiles" diff --git a/.cursor/rules/roblox/en-us/what-is-roblox.md b/.cursor/rules/roblox/en-us/what-is-roblox.md index 69f0d111..7a3f463b 100644 --- a/.cursor/rules/roblox/en-us/what-is-roblox.md +++ b/.cursor/rules/roblox/en-us/what-is-roblox.md @@ -9,7 +9,7 @@ hideInPageNavigation: true
- +
@@ -45,7 +45,7 @@ style={{marginRight:16, alignSelf: 'flex-start'}}>Learn More
- +
Intro to world building Roblox is designed for massive 3D worlds. Learn how to use Roblox Studio to start building! @@ -55,7 +55,7 @@ style={{position: "relative", paddingBottom: "56.25%", height: 0}}>
- +
Intro to physics Roblox is a simulation-first engine that mimics the real world. Learn more about how physics operates in the Roblox Engine. @@ -87,7 +87,7 @@ style={{marginRight:16, alignSelf: 'flex-start'}}>Learn More
- +
Get started with UGC Watch this interview with PolarCub, one of the top UGC item creators on Roblox. @@ -97,7 +97,7 @@ style={{position: "relative", paddingBottom: "56.25%", height: 0}}>
- +
Avatar items Get an overview of everything you can build for Roblox avatars. @@ -108,7 +108,7 @@ style={{position: "relative", paddingBottom: "56.25%", height: 0}}>
- +
Rigid accessories Accessories are items that users can attach to their avatars at a single attachment point. @@ -118,7 +118,7 @@ style={{position: "relative", paddingBottom: "56.25%", height: 0}}>
- +
Layered clothing Build clothing that can layer and stretch on a variety of avatar sizes and shapes. @@ -128,7 +128,7 @@ style={{position: "relative", paddingBottom: "56.25%", height: 0}}>
- +
Custom characters Build completely custom avatar heads and bodies that users can equip. diff --git a/.cursor/rules/vide/.vitepress/config.ts b/.cursor/rules/vide/.vitepress/config.ts new file mode 100644 index 00000000..37918e81 --- /dev/null +++ b/.cursor/rules/vide/.vitepress/config.ts @@ -0,0 +1,83 @@ +//import { defineConfig } from "vitepress" +import { withMermaid } from "vitepress-plugin-mermaid"; + +// https://vitepress.dev/reference/site-config +export default withMermaid({ + title: "Vide", + titleTemplate: ":title - A reactive UI library for Luau", + description: "A reactive UI library for Luau.", + base: "/vide/", + head: [["link", { rel: "icon", href: "/vide/logo.svg" }]], + + themeConfig: { + logo: "/logo.svg", + + search: { + provider: "local" + }, + + footer: { + message: 'Released under the MIT License.', + }, + + // https://vitepress.dev/reference/default-theme-config + nav: [ + { text: "Home", link: "/" }, + { text: "Tutorials", link: "/tut/crash-course/1-introduction" }, + { text: "API", link: "/api/reactivity-core"}, + ], + + sidebar: { + "/api/": [ + { + text: "API", + items: [ + { text: "Reactivity: Core", link: "/api/reactivity-core" }, + { text: "Reactivity: Utility", link: "/api/reactivity-utility" }, + { text: "Reactivity: Dynamic Scoping", link: "/api/reactivity-dynamic" }, + { text: "Element Creation", link: "/api/creation" }, + { text: "Animation", link: "/api/animation" }, + { text: "Strict Mode", link: "/api/strict-mode" }, + ] + } + ], + + "/tut/": [ + { + text: "Crash Course", + items: [ + { text: "Introduction", link: "/tut/crash-course/1-introduction" }, + { text: "Element Creation", link: "/tut/crash-course/2-creation" }, + { text: "Components", link: "/tut/crash-course/3-components" }, + { text: "Sources", link: "/tut/crash-course/4-source" }, + { text: "Effects", link: "/tut/crash-course/5-effect" }, + { text: "Scopes", link: "/tut/crash-course/6-scope" }, + { text: "Reactive Components", link: "/tut/crash-course/7-reactive-component" }, + { text: "Implicit Effects", link: "/tut/crash-course/8-implicit-effect" }, + { text: "Derived Sources", link: "/tut/crash-course/9-derived-source" }, + { text: "Cleanup", link: "/tut/crash-course/10-cleanup" }, + { text: "Dynamic Scopes", link: "/tut/crash-course/11-dynamic-scopes" }, + { text: "Actions", link: "/tut/crash-course/12-actions" }, + { text: "Strict Mode", link: "/tut/crash-course/13-strict-mode" }, + { text: "Concepts Summary", link: "/tut/crash-course/14-concepts" } + ] + }, + { + text: "Advanced", + items: [ + { text: "Dynamic Scopes", link: "/tut/advanced/dynamic-scopes"} + ] + }, + { + text: "Design Patterns", + items: [ + ] + } + ], + }, + + socialLinks: [ + { icon: "github", link: "https://github.com/centau/vide" } + ] + } +}) diff --git a/.cursor/rules/vide/.vitepress/theme/index.css b/.cursor/rules/vide/.vitepress/theme/index.css new file mode 100644 index 00000000..9c3ca9a7 --- /dev/null +++ b/.cursor/rules/vide/.vitepress/theme/index.css @@ -0,0 +1,25 @@ +.home > * > .VPNavBar:not(.top) { + backdrop-filter: blur(0.5rem); + background-color: transparent !important; +} + +.home > * > .VPNavBar > .divider { + opacity: 0; +} + +.home > .VPContent { + display: flex; + justify-content: center; + flex-direction: column; +} + +.VPHome { + margin-top: auto !important; + margin-bottom: auto !important; +} + +.VPBadge a { + text-decoration: none; + color: inherit + } + \ No newline at end of file diff --git a/.cursor/rules/vide/.vitepress/theme/index.js b/.cursor/rules/vide/.vitepress/theme/index.js new file mode 100644 index 00000000..54a4c62e --- /dev/null +++ b/.cursor/rules/vide/.vitepress/theme/index.js @@ -0,0 +1,8 @@ +// .vitepress/theme/index.js +import DefaultTheme from 'vitepress/theme' +import './vars.css' +import './index.css' + +export default { + extends: DefaultTheme, +} diff --git a/.cursor/rules/vide/.vitepress/theme/vars.css b/.cursor/rules/vide/.vitepress/theme/vars.css new file mode 100644 index 00000000..7fbf3b59 --- /dev/null +++ b/.cursor/rules/vide/.vitepress/theme/vars.css @@ -0,0 +1,52 @@ +/* Colors */ + +:root { + --vp-c-brand-1: #3086ff; + --vp-c-brand-2: #75aeff; + + --vp-button-brand-bg: #3661a2; + --vp-button-brand-hover-bg: #24447f; + --vp-button-brand-press-bg: #4896f3; + + --vp-home-hero-name-color: transparent; + --vp-home-hero-name-background: -webkit-linear-gradient( + 120deg, + #3661a2, + #4896f3 + ); + --vp-home-hero-logo-background: -webkit-linear-gradient( + 120deg, + #3661a2, + #4896f3 + ); + + --vp-home-hero-image-filter: blur(96px); + + --vp-c-bg: #f2f5f8; + --vp-c-bg-alt: #dfe8f5; + --vp-c-bg-elv: #dde7f4; + --vp-c-bg-soft: #e8f1fe; + + --vp-c-border: #c0c3c6; + --vp-c-divider: #dfe2e6; + --vp-c-gutter: #dfe2e6; + --vp-plugin-tabs-tab-bg: var(--vp-c-bg); + + --vp-badge-info-bg: #122d26; + --vp-badge-info-text: #6bdbbd; + --vp-badge-tip-bg: #132741; + --vp-badge-tip-text: #70abfa; +} + +.dark { + --vp-c-brand-2: #234782; + --vp-c-bg: #0d131b; + --vp-c-bg-alt: #111720; + --vp-c-bg-elv: #182231; + --vp-c-bg-soft: #182231; + + --vp-c-border: #111720; + --vp-c-divider: #1d273c; + --vp-c-gutter: #181d27; +} + diff --git a/.cursor/rules/vide/api/animation.md b/.cursor/rules/vide/api/animation.md new file mode 100644 index 00000000..ca06b392 --- /dev/null +++ b/.cursor/rules/vide/api/animation.md @@ -0,0 +1,50 @@ +# Animation + +## spring() REACTIVE + +Returns a new source with a value always moving torwards the input source value. + +- **Type** + + ```luau + function spring( + source: () -> T & Animatable, + period: number = 1, + damping_ratio: number = 1 + ): (() -> T, SpringControl) + + type Animatable = number | CFrame | Color3 | UDim | UDim2 | Vector2 | Vector3 | Rect + + type SpringControl = ({ + position: T?, + velocity: T?, + impulse: T? + }) -> () + ``` + +- **Details** + + Creates a reactive scope internally to detect source updates. + + The movement is physically simulated according to a + [spring](https://en.wikipedia.org/wiki/Simple_harmonic_motion). + + `period` is the amount of time in seconds it takes for the spring to + complete one full cycle if undamped. + + `damping_ratio` is the amount of resistance applied to the spring. + + - \>1 = Overdamped - slowly reaches target without any overshoot. + - 1 = Critically damped - reaches target without any overshoot. + - <1 = Underdamped - reaches target with some overshoot. + - 0 = Undamped - never stabilizes, oscillates forever. + + By default, the spring solver is ran at 120 Hz in + [`Heartbeat`](https://create.roblox.com/docs/reference/engine/classes/RunService#Heartbeat). + You can change when the solver runs by calling `vide.step(dt)`, which will + advance the simulation time by `dt` seconds and automatically stop the + solver running in heartbeat. + + ::: warning + Large periods or damping ratios can break the spring. + ::: diff --git a/.cursor/rules/vide/api/creation.md b/.cursor/rules/vide/api/creation.md new file mode 100644 index 00000000..578b10f8 --- /dev/null +++ b/.cursor/rules/vide/api/creation.md @@ -0,0 +1,152 @@ +# Element Creation + +## create() + +Creates a new UI element, applying any given properties. + +- **Type** + + ```luau + function create(class: string): (Properties) -> Instance + function create(instance: Instance): (Properties) -> Instance + + type Properties = Map + ``` + +- **Details** + + The function can take either a `string` or an `Instance` as its first argument. + + - If given a `string`, a new instance with the same class name will be created. + - If given an `Instance`, a new instance that is a clone of the given instance + will be created. + + This returns another function that is used to apply any properties to the new + instance. + +- **Property setting rules** + + - **index is string:** + - **value is function:** + - **property is event:** connect function as callback + - **property is not event:** create effect to update property + - **value is not function:** set property to value + - **index is number:** + - **value is action:** run action + - **value is table:** recurse table + - **value is function:** create effect to update children + - **value is instance:** set instance as child + +- **Example** + + Basic element creation. + + ```luau + local frame = create "TextButton" { + Name = "Button", + Size = UDim2.fromOffset(200, 160), + + Activated = function() + print "clicked" + end, + + create "UICorner" {} + } + ``` + +## action() + +Creates a special object that can be passed to `create()` to invoke custom +actions on instances. + +- **Type** + + ```luau + function action((Instance) -> (), priority: number = 1): Action + ``` + +- **Details** + + When passed to `create()`, the function is called with the instance being + created as the only argument. Actions take precedence over property and + child assignments. + + A priority can be optionally specified to ensure certain actions run after + other actions. Lower priority values are ran first. + +- **Example** + + An action to listen to changed properties: + + ```luau + local function changed(property: string, fn: (new) -> ()) + return action(function(instance) + local cn = instance:GetPropertyChangedSignal(property):Connect(function() + fn(instance[property]) + end) + + -- disconnect on scope destruction to allow gc of instance + cleanup(function() + cn:Disconnect() + end) + end) + end + + local output = source "" + + create "TextBox" { + -- will update the output source anytime the text property is changed + changed("Text", output) + } + ``` + +## changed() + +A wrapper for `action()` to listen for property changes. + +- **Type** + + ```luau + function changed(property: string, fn: (unknown) -> ()): Action + ``` + +- **Details** + + Will run the given function immediately and whenever the property updates. + + The function is called with the updated property value. + + Runs with an action priority of 1. + +## mount() STABLE + +Runs a function in a new stable scope and optionally applies its result to a +target instance. + +- **Type** + + ```luau + function mount(component: () -> T, target: Instance?): () -> () + ``` + +- **Details** + + This is a utility for `root()` when parenting a component to an existing + instance. + + The result of the function is applied to a target in the same way + properties are using `create()`. + + Returns a function that when called will destroy the stable scope. + +- **Example** + + ```luau + local function App() + return create "ScreenGui" { + create "TextLabel" { Text = "Vide" } + } + end + + local destroy = mount(App, game.StarterGui) + ``` diff --git a/.cursor/rules/vide/api/reactivity-core.md b/.cursor/rules/vide/api/reactivity-core.md new file mode 100644 index 00000000..ebbc5dd6 --- /dev/null +++ b/.cursor/rules/vide/api/reactivity-core.md @@ -0,0 +1,155 @@ +# Reactivity: Core + +## Scopes + +Vide code can run in one of two scopes: STABLE or REACTIVE. + +- Reactive scopes rerun if a source read within updates. +- Stable scopes never rerun. +- Reactive scopes cannot be created directly within another reactive scope. +- When a scope is destroyed, all scopes created within are also destroyed. + +Different functions in Vide's API will run code in different scopes. + +:::warning +Yielding is not allowed in any stable or reactive scope. Strict mode will check +for this. +::: + +## root() STABLE + +Runs a function in a new stable scope. + +- **Type** + + ```luau + function root(fn: (Destructor) -> T...): (Destructor, T...) + + type Destructor = () -> () + ``` + +- **Details** + + Returns a destructor and any values returned by the callback. + +## source() + +Creates a new source. + +- **Type** + + ```luau + function source(value: T): Source + + type Source = + () -> T -- get + & (T) -> () -- set + ``` + +- **Details** + + Call the returned source with no argument to read its value. + Call the returned source with an argument to set its value. + +- **Example** + + ```luau + local count = source(0) + print(count())-- 0 + count(count() + 1) + print(count()) -- 1 + ``` + +## effect() REACTIVE + +Runs a function in a new reactive scope. + +- **Type** + + ```luau + function effect(fn: () -> ()) + ``` + +- **Details** + + The function is ran once immediately. + +- **Example** + + ```luau + local count = source(1) + + effect(function() + print(count()) + end) + + -- prints 1 + + count(2) + + -- prints 2 + ``` + +## derive() REACTIVE + +Runs a function in a new reactive scope to compute a value for new source. + +- **Type** + + ```luau + function derive(fn: () -> T): () -> T + ``` + +- **Details** + + Anytime the reactive scope reruns, the output source value is set to what is + returned. + + The function is ran once immediately. + +- **Example** + + ```luau + local count = source(0) + local text = derive(function() return `count: {count()}` end) + + print(text()) -- "count: 0" + + count(1) + + print(text()) -- "count: 1" + ``` + + A `derive()` should be used instead of a pure function when you expect it to + be read multiple times between updates, because `derive()` will cache the + result to prevent recomputing it on every read. + + ::: code-group + + ```luau [Pure Function] + local count = source(0) + + local text = function() + print "ran" + return `count: {count()}` + end + + count(1) + print(text()) -- prints "ran" followed by "count: 1" + print(text()) -- prints "ran" followed by "count: 1" + ``` + + ```luau [Derived Source] + local count = source(0) + + local text = derive(function() -- [!code highlight] + print "ran" + return `count: {count()}` + end) -- [!code highlight] + + count(1) -- prints "ran" + print(text()) -- prints "count: 1" + print(text()) -- prints "count: 1" + ``` + + ::: diff --git a/.cursor/rules/vide/api/reactivity-dynamic.md b/.cursor/rules/vide/api/reactivity-dynamic.md new file mode 100644 index 00000000..f0b32294 --- /dev/null +++ b/.cursor/rules/vide/api/reactivity-dynamic.md @@ -0,0 +1,229 @@ +# Reactivity: Dynamic Scopes + +Dynamic scopes are scopes that are created or destroyed in response to +source updates. Vide provides functions for some common use-cases for dynamic scopes. + +## show() REACTIVE + +Shows a component if the source is truthy. Optionally shows a fallback component +if the source is falsey. + +- **Type** + + ```luau + function show(source: () -> unknown, component: Constructor): () -> T? + function show(source: () -> unknown, component: Constructor, fallback: () -> U): () -> T | U + + type Constructor = () -> (T, number?) + ``` + +- **Details** + + Creates a reactive scope internally to detect source updates. + + The component is run in a stable scope when truthy, otherwise the stable + scope is destroyed. + + Returns a source holding an instance of the currently shown component or + `nil` if no component is currently shown. + + Destruction of the scope can be delayed by returning the number of seconds + to delay by, after the component. + +## switch() REACTIVE + +Shows one of a set of components depending on a source and a mapping table. + +- **Type** + + ```luau + function switch(source: () -> K): (map: Map>): () -> V? + + type Constructor = () -> (T, number?) + ``` + +- **Details** + + Creates a reactive scope internally to detect source updates. + + When the source updates, its value is inputted into a map to get a component + constructor. This component is then run in a stable scope. The previous + stable scope is destroyed. + + Returns a source holding an instance of the currently shown component or + `nil` if no component is currently shown. + + Destruction of the scope can be delayed by returning the number of seconds + to delay by, after the component. + +- **Example** + + ```luau + local logged = source(false) + + local button = switch(logged) { + [true] = function() + return Button { Text = "Log out", Toggle = logged } + end, + + [false] = function() + return Button { Text = "Log in", Toggle = logged } + end + } + ``` + +## indexes() REACTIVE + +Shows a component for each index in a table. + +- **Type** + + ```luau + function indexes( + source: () -> Map, + constructor: (value: () -> VI, index: KI) -> (VO, number?) + ): Array + ``` + +- **Details** + + Creates a reactive scope internally to detect source updates. + + When the source table updates, a component is generated for each index in + the table. + + - For any added index, the `constructor` function is run in a new stable + scope to produce an instance that is cached. + - For any removed index, the stable scope for that index is destroyed. + + The `constructor` function is called with: + + 1. A *source containing the index's value*. + 2. The *index itself*. + + Anytime an existing index's value changes, the `constructor` function is not + rerun, instead, that index's corresponding source is updated with the new + value. + + Returns a source holding an array of instances currently shown. + + Destruction of the scope can be delayed by returning the number of seconds + to delay by, after the component. + +- **Example** + + ```luau + type Item = { + name: string, + icon: number + } + + local items = source {} :: () -> Array + + local displays = indexes(items, function(item, i) + return ItemDisplay { + Name = function() + return i .. ": " .. item().name + end, + + Image = function() + return "rbxassetid://" .. item().icon + end, + } + end) + ``` + +## values() REACTIVE + +Shows a component for each value in a table. + +- **Type** + + ```luau + function values( + source: () -> Map, + constructor: (value: VI, index: () -> KI) -> (VO, number?) + ): Array + +- **Details** + + Operates with the same idea as `indexes()`, but applied to values instead of + indexes. + + Creates a reactive scope internally to detect source updates. + + When the source table updates, a component is generated for each value in + the table. + + - For any added value, the `constructor` function is run in a new stable scope + to produce an instance that is cached. + - For any removed value, the stable scope for that value is destroyed. + + The `constructor` function is called with: + + 1. The *value itself*. + 2. A *source containing the value's index*. + + Anytime an existing value's index changes, the `constructor` function is not + rerun, instead, that value's corresponding source is updated with the new + index. + + Returns a source holding an array of instances currently shown. + + Destruction of the scope can be delayed by returning the number of seconds + to delay by, after the component. + + ::: warning + Having the same values appear multiple times in the input source table can + cause unexpected behavior. Strict mode has checks for this. + ::: + +- **Example** + + ```luau + type Item = { + name: string, + icon: number + } + + local items = source {} :: () -> Array + + local displays = values(items, function(item, i) + return ItemDisplay { + Name = function() + return i() .. ": " .. item.Name + end + + Image = "rbxassetid://" .. item.icon, + } + end) + ``` + +- **Extra** + + When should you use `indexes()` and `values()`? + + `values()` should be used when you have a fixed set of objects where the + same objects can be re-arranged in the source table. It maps a value to a + UI element. + + e.g. + - List of all players. + - Inventory of items. + - Chat message history. + - Toast notifications. + + `indexes()` should be used in other cases, especially when your source table + has primitive values. It maps an index to a UI element. + + e.g. + - List of character or weapon stats. + + In most cases, both functions will produce the same observed result. + The main difference is performance, picking the right function to use can + result in less property updates and less re-renders. One case to note is + that `values()` works nicely when animating re-ordering of instances, since + the source index can be used to animate a change in position for the UI + element. + +-------------------------------------------------------------------------------- diff --git a/.cursor/rules/vide/api/reactivity-utility.md b/.cursor/rules/vide/api/reactivity-utility.md new file mode 100644 index 00000000..b8bff4d4 --- /dev/null +++ b/.cursor/rules/vide/api/reactivity-utility.md @@ -0,0 +1,158 @@ +# Reactivity: Utility + +## cleanup() + +Queues a callback to run when a scope is reran or destroyed. + +- **Type** + + ```luau + function cleanup(v: Function | Disconnectable | Destroyable | thread) + + type Function = () -> () + type Destroyable = { destroy: () -> () } + type Disconnectable = { disconnect: () -> () } + ``` + +- **Example** + + ```luau + local count = source(0) + + local destroy = root(function() + effect(function() + count() + + cleanup(function() + print "cleaned" + end) + end) + end + + -- nothing printed yet + count(1) -- prints "cleaned" + count(2) -- prints "cleaned" + destroy() -- prints "cleaned" + ``` + +## untrack() STABLE + +Runs a function in a new stable scope. + +- **Type** + + ```luau + function untrack(source: () -> T): T + ``` + +- **Details** + + Can be used inside a reactive scope to read from sources you do not want + tracked by the reactive scope. + +- **Example** + + ```luau + local a = source(0) + local b = source(0) + + local sum = derive(function() + return a() + untrack(b) + end) + + print(sum()) -- 0 + b(1) -- untracked so reactive scope created by derive() does not rerun + print(sum()) -- 0 + a(1) -- reactive scope created by derive() reruns + print(sum()) -- 2 + ``` + +## read() + +Utility used to read a value that is either a primitive or a source. + +- **Type** + + ```luau + function read(value: T | () -> T): T + ``` + +## batch() + +Runs a function where any source updates made within the function do not +trigger effects until after the function ends. + +- **Type** + + ```luau + function batch(fn: () -> ()) + ``` + +- **Details** + + Improves performance when an effect depends on multiple sources, and those + sources need to be updated. + +- **Example** + + ```luau + local a = source(0) + local b = source(0) + + effect(function() + print(a() + b()) + end) + + -- prints "0" + + batch(function() + a(1) -- no print + b(2) -- no print + end) + + -- prints "3" + ``` + +## context() STABLE + +Creates a new context. + +- **Type** + + ```luau + function context(default: T): Context + + type Context = + () -> T -- get + & (T, () -> U) -> U -- set + ``` + +- **Details** + + Calling `context()` returns a new context function. + Call this function with no arguments to get the context value. + Call this function with a value and a function to create a new context with + the given value. + + The new context is run under a stable scope. + +- **Example** + + ```luau + local theme = context() + + local function Button() + print(theme()) + end + + root(function() + theme("light", function() + Button() -- prints "light" + + theme("dark", function() + Button() -- prints "dark" + end) + end) + end) + ``` + diff --git a/.cursor/rules/vide/api/strict-mode.md b/.cursor/rules/vide/api/strict-mode.md new file mode 100644 index 00000000..6f9ee80b --- /dev/null +++ b/.cursor/rules/vide/api/strict-mode.md @@ -0,0 +1,37 @@ +# Strict Mode + +Strict mode is library-wide and can get set by doing: + +```luau +vide.strict = true +``` + +It is automatically enabled when Vide is first required and not running in O2 +optimization level. + +Strict mode is designed to help the development process by adding safety checks +and identifying improper usage. + +Currently, strict mode will: + +1. Run reactive scopes twice when a source updates. +2. Throw an error if yields occur where they are not allowed. +3. Checks for `indexes()` and `values()` outputting primitive values. +4. Checks for `values()` input having duplicate values. +5. Checks for duplicate nested properties at same depth. +6. Checks for destruction of an active scope. +7. Better error reporting and stack traces. + +By rerunning reactive scopes twice each time they update, it helps ensure that +computations are pure, and that any cleanup is done correctly. + +Accidental yielding within reactive scopes can break Vide's reactive graph, +which strict mode will catch. + +As well as additional safety checks, Vide will dedicate extra resources to +recording and better emitting stack traces where errors occur, particularly +when implicit effects are created for instance property updating. + +It is recommended to develop UI with strict mode and to disable it when pushing to +production. In Roblox, production code compiles at O2 by default, so you do not +need to worry about disabling strict mode unless you have manually enabled it. diff --git a/.cursor/rules/vide/index.md b/.cursor/rules/vide/index.md new file mode 100644 index 00000000..295d1371 --- /dev/null +++ b/.cursor/rules/vide/index.md @@ -0,0 +1,22 @@ +--- +# https://vitepress.dev/reference/default-theme-home-page +layout: home +pageClass: home +next: + text: 'Introduction' + link: '/tut/crash-course/1-introduction' + +hero: + name: "Vide" + tagline: A reactive UI library for Luau. + image: + src: /logo.svg + actions: + - theme: brand + text: Tutorials + link: /tut/crash-course/1-introduction + - theme: alt + text: API Reference + link: /api/reactivity-core + +--- diff --git a/.cursor/rules/vide/package.json b/.cursor/rules/vide/package.json new file mode 100644 index 00000000..a329007b --- /dev/null +++ b/.cursor/rules/vide/package.json @@ -0,0 +1,12 @@ +{ + "type": "module", + "scripts": { + "docs:dev": "vitepress dev", + "docs:build": "vitepress build", + "docs:preview": "vitepress preview" + }, + "devDependencies": { + "vitepress": "^1.4.5", + "vitepress-plugin-mermaid": "2.0.17" + } +} diff --git a/.cursor/rules/vide/public/full_logo.svg b/.cursor/rules/vide/public/full_logo.svg new file mode 100644 index 00000000..19628006 --- /dev/null +++ b/.cursor/rules/vide/public/full_logo.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.cursor/rules/vide/public/logo.svg b/.cursor/rules/vide/public/logo.svg new file mode 100644 index 00000000..22d840a2 --- /dev/null +++ b/.cursor/rules/vide/public/logo.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.cursor/rules/vide/tut/advanced/dynamic-scopes.md b/.cursor/rules/vide/tut/advanced/dynamic-scopes.md new file mode 100644 index 00000000..139a19cc --- /dev/null +++ b/.cursor/rules/vide/tut/advanced/dynamic-scopes.md @@ -0,0 +1,148 @@ +# Dynamic Scopes + +Dynamic scopes are scopes that are created and destroyed in response to +source updates. This is needed for conditionally rendering parts of your UI, +such as opening and closing menus. + +While Vide provides functions for common ways to do this, this section will +show how you can implement them yourself so you are not limited by only what is +provided. + +## Recreating [`show()`](/api/reactivity-dynamic#show-reactive) + +The most basic one, `show()`, can be +implemented yourself like so: + +```luau +local function show(toggle: () -> unknown, component: () -> Instance) + return derive(function() + return if toggle() then untrack(component) else nil + end) +end +``` + +The main thing to note here is the use of `untrack()`. This function runs its +callback in a new stable scope. Without this, if the component were to create +a reactive scope, an error would occur since a reactive scope cannot be created +within a reactive scope. + +```mermaid +%%{init: { + "theme": "base", + "themeVariables": { + "primaryColor": "#111720", + "primaryTextColor": "#fff", + "primaryBorderColor": "#444455", + "lineColor": "#79B8FF", + "tertiaryColor": "#0d131b", + "tertiaryBorderColor": "#444455" + } +}}%% + +graph + +subgraph derive ["derive (reactive)"] + + subgraph untrack ["untrack (stable)"] + subgraph effect ["effect (reactive)"] + + end + end +end +``` + +You can see from the above graph how the effect would not be created directly +inside the derive, there is a stable scope between them. This requirement exists +as a guard against unintentional rerendering of UI. + +## Recreating [`switch()`](/api/reactivity-dynamic#switch-reactive) + +```luau +local function switch(key) + return function(map) + return derive(function() + local component = map[key()] + return if component then untrack(component) else nil + end) + end +end +``` + +## Recreating [`indexes()`](/api/reactivity-dynamic#indexes-reactive) + +This is a more complicated function because it manages multiple scopes at the +same time, unlike the previous functions. Because some scopes may persist +between reruns, we cannot use `untrack()` anymore which automatically destroys +on rerun; we must use `root()` where the lifetime of each scope is managed +manually and independently. + +```luau +local function indexes( + input: () -> Map, + transform: (value: () -> VI, index: I) -> VO +) + local index_caches = {} :: Map VI, + destroy: () -> () + }?> + + -- destroy all scopes if the parent scope is destroyed + cleanup(function() + for _, cache in index_caches do + assert(cache).destroy() + end + end) + + return derive(function() + local new_input = input() + + -- destroy scopes of removed indexes + for i, cache in index_caches do + if new_input[i] == nil then + assert(cache).destroy() + index_caches[i] = nil + end + end + + -- create scopes or update sources of added or changed index values + for i, v in new_input do + local cache = index_caches[i] + + if cache == nil then -- no scope created for this index, create one + local src = source(v) + + local destroy, result = root(function() + return transform(src, i) + end) + + index_caches[i] = { + destroy = destroy, + source = src, + output = result, + previous_input = v + } + elseif cache.previous_input ~= v then -- scope exists, update source + cache.previous_input = v + cache.source(v) + else -- scope exists and value has not changed; do nothing + end + end + + -- return the cached output values as an array + local array = table.create(#index_caches) + + for _, cache in index_caches do + table.insert(array, assert(cache).output) + end + + return array + end) +end +``` + +-------------------------------------------------------------------------------- + +Though the above functions are already provided to you by Vide, this serves as +an example for how you may create your own dynamic scope functions. diff --git a/.cursor/rules/vide/tut/crash-course/1-introduction.md b/.cursor/rules/vide/tut/crash-course/1-introduction.md new file mode 100644 index 00000000..564aa2d3 --- /dev/null +++ b/.cursor/rules/vide/tut/crash-course/1-introduction.md @@ -0,0 +1,21 @@ +# Introduction + +This is a tutorial that introduces the concepts and usage of Vide. + +Vide is heavily inspired by [Solid](https://www.solidjs.com/). + +## Why Vide? + +Vide's reactive and declarative API aims to let you program UI as simply as +possible, with a strong focus on how data flows through your application. + +Some of Vide's main design choices: + +- Syntax minimal. +- Data oriented. +- Typechecking compatible. +- Instance independent. + +Vide's reactivity operates with the concept +of scopes which carries a learning curve, though is what makes Vide's minimal +syntax possible. The crash course will introduce these concepts gradually. diff --git a/.cursor/rules/vide/tut/crash-course/10-cleanup.md b/.cursor/rules/vide/tut/crash-course/10-cleanup.md new file mode 100644 index 00000000..e25d451c --- /dev/null +++ b/.cursor/rules/vide/tut/crash-course/10-cleanup.md @@ -0,0 +1,38 @@ +# Cleanup + +Sometimes you may need to do some cleanup when destroying a component or after +a side-effect from a source update. Vide provides a function `cleanup()` which +is used to queue a callback for the next time a reactive scope is rerun or +destroyed, or when a stable scope is destroyed. + +```luau +local root = vide.root +local source = vide.source +local effect = vide.effect +local cleanup = vide.cleanup + +local count = source(0) + +local destroy = root(function() + effect(function() + local x = count() + cleanup(function() print(x) end) + end) + + cleanup(function() print "root destroyed" end) +end) + +count(1) -- prints "0" +count(2) -- prints "1" +destroy() -- prints "2" and "root destroyed" +``` + +::: tip +Roblox instances do not need to be explicitly destroyed for their +memory to be freed, they only need to be parented to `nil`. So there is no +need to use `cleanup()` to destroy instances. However, be wary of connecting +a function that references an instance to an event from the same instance, +this causes the instance to reference itself and never be freed. In such a case +you would need to use `cleanup()` to disconnect this connection or to explicitly +destroy the instance. +::: diff --git a/.cursor/rules/vide/tut/crash-course/11-dynamic-scopes.md b/.cursor/rules/vide/tut/crash-course/11-dynamic-scopes.md new file mode 100644 index 00000000..1c12e51d --- /dev/null +++ b/.cursor/rules/vide/tut/crash-course/11-dynamic-scopes.md @@ -0,0 +1,211 @@ +# Dynamic Scopes + +Eventually you may need a way to dynamically create and destroy UI elements +resulting from source updates. Vide provides functions to help you do this, +known as *dynamic scope* functions. + +These functions create and destroy scopes for you in response to source +updates. They return a source containing the created component. This source can +be parented as a child which will update the shown children whenever the source +updates. + +The simplest example is using `show()`. + +```luau +local source = vide.source +local create = vide.create +local show = vide.show +local root = vide.root + +function Button(props: { Text: string, Activated: () -> () }) + return create "TextButton" { + Text = props.Text, + Activated = props.Activated + } +end + +function Menu() + return create "TextLabel" { + Text = "This is a menu" + } +end + +function App() + local toggled = source(false) + + return create "ScreenGui" { + Button { + Text = "Toggle Menu", + Activated = function() + toggled(not toggled()) + end + }, + + show(toggled, Menu) -- [!code highlight] + } +end + +root(function() + App().Parent = game.StarterGui +end) +``` + +This is a complete example of rendering UI which has a single button that +toggles the opening of a menu. + +-------------------------------------------------------------------------------- + +Another common function is `indexes()`. This function creates a component for +each index in a table. + +Each component created is done so in a new and independent stable scope. The +indexes of the table are checked each source update to prevent redunant +destruction and recreation of UI elements. + +```luau +local source = vide.source +local create = vide.create +local indexes = vide.indexes +local root = vide.root + +local function Todo(props: { + Text: () -> string, + Position: number, + Activated: () -> () +}) + return create "TextButton" { + Text = function() return props.Position .. ": " .. props.Text() end, + LayoutOrder = props.Position, + Activated = Activated + } +end + +local function TodoList(props: { List: () -> Array }) + return create "Frame" { + create "UIListLayout" {}, + + indexes(props.List, function(text, i) -- [!code highlight] + return Todo { + Text = text, + Position = i, + Activated = function() -- remove the todo when clicked + local list = props.List() + table.remove(list, i) + props.List(list) + end + } + end) + } +end + +function App() + local list = source { + "finish the crash course", + "star Vide's GitHub" + } + + return create "ScreenGui" { + TodoList { List = list }, + } +end + +root(function() + App().Parent = game.StarterGui +end) +``` + +The reactive graph for the above example: + +```mermaid +%%{init: { + "theme": "base", + "themeVariables": { + "primaryColor": "#111720", + "primaryTextColor": "#fff", + "primaryBorderColor": "#111720", + "lineColor": "#79B8FF", + "tertiaryColor": "#0d131b", + "tertiaryBorderColor": "#0d131b" + } +}}%% + +graph + +subgraph root ["root"] + direction LR + todoList --> indexes -.- subroot1 & subroot2 + + subgraph subroot1 ["indexes scope 1"] + direction LR + value1[todo] --> prop1["prop binding"] + end + + subgraph subroot2 ["indexes scope 2"] + direction LR + value2[todo] --> prop2[prop binding] + end +end +``` + +When you edit a table in a source, you must set that table again to actually +update the source. + +```luau +local src = source { 1, 2 } +local data = src() +table.insert(data, 3) -- no effects will run +src(data) -- effects will run +``` + +-------------------------------------------------------------------------------- + +All dynamic scope functions also support delaying the destruction of the scope. +This is useful for playing any sort of animation or effect before the UI +instance is removed. + +If you have the following code, for example: + +```lua +local function Menu() + return create "Frame" {} +end + +local toggled = source(true) + +create "ScreenGui" { + show(toggled, function() + return Menu {} + end) +} + +toggled(false) -- menu will disappear immediately +``` + +```lua +local function Menu(props: { Visible: () -> boolean }) + local transparency = spring(function() + return if p.Visible then 0 else 1 + end + + return create "Frame" { + BackgroundTransparency = transparency + } +end + +local toggled = source(true) + +create "ScreenGui" { + show(toggled, function(_, present) + return Menu { p.Visible = present }, 3 -- give a generous 3 seconds for the spring to complete before destroying + end) +} + +toggled(false) +-- `present` will go `false` immediately +-- transparency will begin being sprung +-- after 3 seconds the scope is destroyed, giving the spring enough time to complete +``` + +If `toggled` goes from truthy to falsey, beginning the timer, but then back +to truthy before the timer finishes, the timer is cancelled and the scope is +not destroyed. diff --git a/.cursor/rules/vide/tut/crash-course/12-actions.md b/.cursor/rules/vide/tut/crash-course/12-actions.md new file mode 100644 index 00000000..60e5c30e --- /dev/null +++ b/.cursor/rules/vide/tut/crash-course/12-actions.md @@ -0,0 +1,55 @@ +# Actions + +Actions are special callbacks that you can pass along with properties, +to run some code on an instance receiving them. + +```luau +local action = vide.action + +create "TextLabel" { + Text = "test", + + action(function(instance) + print(instance.Text) + end) +} + +-- will print "test" +``` + +Actions can be wrapped with functions for reuse. Below is an example of an +action used to listen for property changes: + +```luau +local action = vide.action +local source = vide.source +local effect = vide.effect +local cleanup = vide.cleanup + +local function changed(property: string, callback: (new) -> ()) + return action(function(instance) + local connection = instance:GetPropertyChangedSignal(property):Connect(function() + callback(instance[property]) + end) + + -- remember to clean up the connection when the reactive scope the action + -- is ran in is destroyed, so the instance can be garbage collected + cleanup(connection) + end) +end + +local output = source "" + +local instance = create "TextBox" { + changed("Text", output) +} + +effect(function() + print(output()) +end) + +instance.Text = "foo" -- "foo" will be printed by the effect +``` + +The source `output` will be updated with the new property value any time it is +changed externally. diff --git a/.cursor/rules/vide/tut/crash-course/13-strict-mode.md b/.cursor/rules/vide/tut/crash-course/13-strict-mode.md new file mode 100644 index 00000000..0de8887f --- /dev/null +++ b/.cursor/rules/vide/tut/crash-course/13-strict-mode.md @@ -0,0 +1,36 @@ +# Strict Mode + +While developing UI with Vide, you should use Vide's strict mode, which can +be set with `vide.strict = true` once when you first require Vide. Strict mode +will add extra safety checks and emit better error traces, particularly when +errors occur in property bindings. + +Strict mode is automatically enabled when Vide is required in O0 or O1 +optimization (default studio level). You can `vide.strict = false` if you do not +want this. + +Strict mode will run derived sources and effects twice each time they update. +This is to help ensure that derived source computations are pure, and that any +cleanups made in derived sources or effects are done properly. + +```luau +local source = vide.source +local effect = vide.effect + +vide.strict = true + +local count = source(0) + +local ran = 0 +effect(function() + count() + ran += 1 +end) + +print(ran) -- 2 +count(1) +print(ran) -- 4 +``` + +A full list of what strict mode will do can be found +[here](../../api/strict-mode). diff --git a/.cursor/rules/vide/tut/crash-course/14-concepts.md b/.cursor/rules/vide/tut/crash-course/14-concepts.md new file mode 100644 index 00000000..f33d043d --- /dev/null +++ b/.cursor/rules/vide/tut/crash-course/14-concepts.md @@ -0,0 +1,113 @@ +# Concepts Summary + +A summary of all the concepts covered during the crash course. + +## Source + +A source of data. + +Stores a single value that can be updated. + +Created with `source()`. + +## Derived Source + +A new source composed of other sources. + +Created with a plain function or with `derive()`. + +## Effect + +Anything that happens in response to a source update. + +Created with `effect()`. + +## Stable Scope + +One of the two types of Vide scopes. + +Created by: + +- `root()` +- `untrack()` +- `show()` +- `indexes()` + +Stable scopes do not track sources and never rerun. + +New stable or reactive scopes can be created within a stable scope. + +## Reactive Scope + +Created by: + +- `effect()` +- `derive()` + +Reactive scopes do track sources and will rerun when those sources update. + +Reactive scopes cannot be created within a reactive scope, but stable scopes +can be created within a reactive scope. + +## Scope Cleanup + +When a scope is rerun or destroyed, all scopes created within it are +automatically destroyed. + +Any functions queued by `cleanup()` are also ran. + +## Reactive Graph + +The combination of stable and reactive scopes can viewed graphically, called a +*reactive graph*. This can be a more intuitive way to think of the +relationships between effects and the sources they depend on. + +### Code + +```luau +local count = source(0) + +root(function() + local text = derive(function() + return "count: " .. count() + end) + + effect(function() + print(text()) + end) +end) +``` + +### Graph resulting from code + +```mermaid +%%{init: { + "theme": "base", + "themeVariables": { + "primaryColor": "#111720", + "primaryTextColor": "#fff", + "primaryBorderColor": "#111720", + "lineColor": "#79B8FF", + "tertiaryColor": "#0d131b", + "tertiaryBorderColor": "#202530" + } +}}%% + +graph LR + +subgraph root + text --> effect +end + +count --> text +``` + +Notes: + +- Since `count` is a source, not an effect, it can exist + outside of scopes. +- An update to `count` will cause `text` to rerun, which + then causes `effect` to rerun. +- When the root scope is destroyed, `text` and + `effect` will be destroyed alongside it, since they were created within it. + `count` will be untouched and future updates to `count` will have no effect. diff --git a/.cursor/rules/vide/tut/crash-course/2-creation.md b/.cursor/rules/vide/tut/crash-course/2-creation.md new file mode 100644 index 00000000..668a4709 --- /dev/null +++ b/.cursor/rules/vide/tut/crash-course/2-creation.md @@ -0,0 +1,38 @@ +# Creating UI + +Instances are created using `create()`. + +Parentheses `()` can be omitted when calling functions with string or +table literals for brevity. + +```luau +local create = vide.create + +return create "ScreenGui" { + create "Frame" { + AnchorPoint = Vector2.new(0.5, 0.5), + Position = UDim2.fromScale(0.5, 0.5), + Size = UDim2.fromScale(0.4, 0.7), + + create "TextLabel" { + Text = "hi" + }, + + create "TextLabel" { + Text = "bye" + }, + + create "TextButton" { + Text = "click me", + + Activated = function() + print "clicked!" + end + } + } +} +``` + +Assign a value to a string key to set a property, and assign a value to a +number key to set a child. Events can be connected to by assigning a function +to a string key. diff --git a/.cursor/rules/vide/tut/crash-course/3-components.md b/.cursor/rules/vide/tut/crash-course/3-components.md new file mode 100644 index 00000000..0b803ca5 --- /dev/null +++ b/.cursor/rules/vide/tut/crash-course/3-components.md @@ -0,0 +1,65 @@ +# Components + +Vide encourages separating different parts of your UI into functions called +*components*. + +A component is a function that creates and returns a piece of UI. + +This is a way to separate your UI into small chunks that you can reuse and put +together. + +::: code-group + +```luau [Button.luau] +local create = vide.create + +local function Button(props: { + Position: UDim2, + Text: string, + Activated: () -> () +}) + return create "TextButton" { + BackgroundColor3 = Color3.fromRGB(50, 50, 50), + TextColor3 = Color3.fromRGB(255, 255, 255), + Size = UDim2.fromOffset(200, 150), + + Position = props.Position, + Text = props.Text, + Activated = props.Activated, + + create "UICorner" {} + } +end + +return Button +``` + +```luau [Menu.luau] +local create = vide.create + +local Button = require(Button) + +local function Menu() + return create "ScreenGui" { + Button { + Position = UDim2.fromOffset(200, 200), + Text = "back", + Activated = function() + print "go to previous page" + end + }, + + Button { + Position = UDim2.fromOffset(400, 200), + Text = "next", + Activated = function() + print "go to next page" + end + } + } +end +``` + +::: + +A single parameter `props` is used to pass properties to the component. diff --git a/.cursor/rules/vide/tut/crash-course/4-source.md b/.cursor/rules/vide/tut/crash-course/4-source.md new file mode 100644 index 00000000..d862156d --- /dev/null +++ b/.cursor/rules/vide/tut/crash-course/4-source.md @@ -0,0 +1,38 @@ +# Sources + +Sources are special objects that store a single value and are the core of +Vide's reactivity. + +A source can be created using `source()`. + +```luau +local source = vide.source + +local count = source(0) +``` + +The value passed to `source()` is the initial value of the source. + +The value of a source can be set by calling it with an argument, and can be read +by calling it with no arguments. + +```luau +count(count() + 1) -- increment count by 1 +``` + +Sources can be *derived* by wrapping them in functions. + +```luau +local count = source(0) + +local text = function() + return "count: " .. tostring(count()) +end + +print(text()) -- "count: 0" +count(1) +print(text()) -- "count: 1" +``` + +While the above can be achieved with plain variables, the use for sources will +be obvious in the next part. diff --git a/.cursor/rules/vide/tut/crash-course/5-effect.md b/.cursor/rules/vide/tut/crash-course/5-effect.md new file mode 100644 index 00000000..82768dc0 --- /dev/null +++ b/.cursor/rules/vide/tut/crash-course/5-effect.md @@ -0,0 +1,71 @@ +# Effects + +Effects are functions that are ran in response to source updates. +A source and effect is analogous to a signal and connection. + +Effects are created using `effect()`. + +```luau +local source = vide.source +local effect = vide.effect + +local count = source(0) + +effect(function() + print("count: " .. count()) +end) + +-- "count: 0" printed +count(1) +-- "count: 1" printed +``` + +Any source read inside an effect is tracked and will rerun the effect when +that source is updated. + +The effect runs its callback once immediately to initially figure out what +sources are being read. + +Derived sources are also tracked, it does not matter how deeply nested +inside a function a source is. + +```luau +local source = vide.source +local effect = vide.effect + +local count = source(1) + +local doubled = function() + return count() * 2 +end + +effect(function() + print("doubled count: " .. doubled()) +end) + +-- "doubled count: 2" printed +count(2) +-- "doubled count: 4" printed +``` + +If a source is updated with the same value it already had, it will not rerun +effects depending on it. + +You can also read from a source within an effect without the effect tracking it. + +```luau +local source = vide.source +local effect = vide.effect +local untrack = vide.untrack + +local a = source(0) +local b = source(0) + +effect(function() + print(`a: {a()} b: {untrack(b)}`) +end) + +a(1) -- prints "a: 1 b: 0" +b(1) -- prints nothing +a(2) -- prints "a: 2 b: 1" +``` diff --git a/.cursor/rules/vide/tut/crash-course/6-scope.md b/.cursor/rules/vide/tut/crash-course/6-scope.md new file mode 100644 index 00000000..e2cea69c --- /dev/null +++ b/.cursor/rules/vide/tut/crash-course/6-scope.md @@ -0,0 +1,88 @@ +# Scopes + +Just like how a signal's connection may need to be disconnected, a source's +effect also may need to be disconnected. + +But the disconnecting of many signals and connections is tedious and verbose. +Vide instead operates on the concept of scopes which provides a much cleaner +API, given that you follow a few rules. + +There are two types of scopes: stable and reactive. + +- A scope must be created within another scope. +- Stable scopes never rerun. +- Reactive scopes can rerun. +- A reactive scope cannot be created within another reactive scope, only within + a stable scope. + +An exception to the first rule is `root()`, which creates the initial scope that +you destroy manually with a destructor function it returns. + +`root()` creates a stable scope. +`effect()` creates a reactive scope. + +Whenever a scope is destroyed, any scope created within that scope is also +destroyed, and so on. + +```luau +local root = vide.root +local source = vide.source +local effect = vide.effect + +local count = source(0) + +local function setup() + effect(function() + print(count()) + end) +end + +setup() -- error, effect() tried to create a reactive scope with no stable scope + +local destroy = root(setup) -- ok since effect() was called in a stable scope + +count(1) -- prints "1" +count(2) -- prints "2" + +destroy() + +count(3) -- reactive scope created by effect() is destroyed, it does not rerun +``` + +Vide's reactivity can be represented graphically, as a *reactive graph*. + +The reactive graph for the above example looks like so: + +```mermaid +%%{init: { + "theme": "base", + "themeVariables": { + "primaryColor": "#111720", + "primaryTextColor": "#fff", + "primaryBorderColor": "#111720", + "lineColor": "#79B8FF", + "tertiaryColor": "#0d131b", + "tertiaryBorderColor": "#0d131b" + } +}}%% + +graph + +subgraph root + direction LR + count --> effect +end +``` + +When the stable `root()` scope is destroyed, the reactive `effect()` +scope will also be destroyed since it was created within it. + +This is important because you may have an effect that updates the property of a +UI instance, meaning the effect is referencing and holding that instance in +memory. The effect being destroyed will remove this reference, allowing the +instance to be garbage collected. + +You don't need to worry about ensuring all your effects are created within a +stable scope, since you should be creating all your UI and effects within a +single top-level `root()` call that puts all your UI together, making it safe to +assume any effect created will be created under this stable scope. diff --git a/.cursor/rules/vide/tut/crash-course/7-reactive-component.md b/.cursor/rules/vide/tut/crash-course/7-reactive-component.md new file mode 100644 index 00000000..339ee4f8 --- /dev/null +++ b/.cursor/rules/vide/tut/crash-course/7-reactive-component.md @@ -0,0 +1,60 @@ +# Reactive Components + +Reactive components in Vide are created using sources and effects - sources to +store the data, and effects to display the data. + +```luau +local create = vide.create +local source = vide.source +local effect = vide.effect + +local function Counter() + local count = source(0) + + local instance = create "TextButton" { + Activated = function() + count(count() + 1) + end + } + + effect(function() + instance.Text = "count: " .. count() + end) + + return instance +end +``` + +Above is an example of a counter component, that when clicked, will increment +its internal count, and automatically update its text to reflect that count. + +Each instance of `Counter()` will maintain its own independent count, since the +count source is created inside the component. + +External sources can also be passed into components for them to use. + +```luau +local function CountDisplay(props: { count: () -> number }) + local count = props.count + + local instance = create "TextLabel" {} + + effect(function() + instance.Text = "count: " .. count() + end) + + return instance +end + +local count = source(0) + +CountDisplay { + count = count +} + +count(1) -- the CountDisplay component will update to display this count +``` + +Sources can be created internally or passed in from externally, there are no +restrictions on how they are used as long as the effect using it is created +within a stable scope. diff --git a/.cursor/rules/vide/tut/crash-course/8-implicit-effect.md b/.cursor/rules/vide/tut/crash-course/8-implicit-effect.md new file mode 100644 index 00000000..3363bf69 --- /dev/null +++ b/.cursor/rules/vide/tut/crash-course/8-implicit-effect.md @@ -0,0 +1,83 @@ +# Implicit Effects + +Explicitly creating effects to update properties is tedious. You can +*implicitly* create an effect to update properties instead. + +::: code-group + +```luau [Implicit Effect] +local create = vide.create +local source = vide.source + +local function Counter() + local count = source(0) + + return create "TextButton" { + Activated = function() + count(count() + 1) + end, + + Text = function() + return "count: " .. count() + end + } +end +``` + +```luau [Explicit Effect] +local create = vide.create +local source = vide.source +local effect = vide.effect + +local function Counter() + local count = source(0) + + local instance = create "TextButton" { + Activated = function() + count(count() + 1) + end + } + + effect(function() + instance.Text = "count: " .. count() + end) + + return instance +end +``` + +::: + +This example is equivalent to the example seen on the previous page. + +Instead of explicitly creating an effect, assigning a (non-event) property a +function will implicitly create an effect to update that property. + +## Children + +Children can also be set in a similar manner. A source passed as a child (passed +with a number key instead of string key) can return an instance or an array of +instances. An effect is automatically created to unparent removed instances and +parent new instances on source update. + +```luau +local items = source { + create "TextLabel" { Text = "A" } +} + +local function List(props: { children: () -> { Instance } }) + return create "Frame" { + create "UIListLayout" {}, + props.children + } +end + +local list = List { children = items } -- creates a list with text label "A" + +items { + create "TextLabel" { Text = "B" }, + create "TextLabel" { Text = "C" } +} + +-- this will automatically unparent text label "A", and parent labels "B" and "C" +``` diff --git a/.cursor/rules/vide/tut/crash-course/9-derived-source.md b/.cursor/rules/vide/tut/crash-course/9-derived-source.md new file mode 100644 index 00000000..694d90b5 --- /dev/null +++ b/.cursor/rules/vide/tut/crash-course/9-derived-source.md @@ -0,0 +1,93 @@ +# Derived Sources + +We have seen the basic way to derive a source: + +```luau +local count = source(0) + +local text = function() + return "count: " .. tostring(count()) +end + +print(text()) -- "count: 0" +count(1) +print(text()) -- "count: 1" +``` + +However, in some cases where this source could be used by multiple effects at +the same time, the function wrapping the source will needlessly rerun to convert +the count into a string for each effect using it. + +```luau +local source = vide.source +local effect = vide.effect + +local count = source(0) + +local text = function() + print "ran" + return "count: " .. tostring(count()) +end + +effect(function() text() end) +effect(function() text() end) + +count(1) -- prints "ran" x2 +``` + +To avoid this, you can use `derive()` to derive a new source instead. This will +run a function in a reactive scope only when a source used inside updated. +Reading this derived source multiple times will just return a cached result. + +```luau +local source = vide.source +local effect = vide.effect +local derive = vide.derive + +local count = source(0) + +local text = derive(function() + print "ran" + return "count: " .. tostring(count()) +end) + +effect(function() text() end) +effect(function() text() end) + +count(1) -- prints "ran" x1 +``` + +Because `derive()` creates a reactive scope, it must be called within a stable +scope, just like `effect()`. + +If the recalculated value is the same as the old value, the derived source will +not rerun the effects using it. + +The reactive graph for the above example: + +```mermaid +%%{init: { + "theme": "base", + "themeVariables": { + "primaryColor": "#111720", + "primaryTextColor": "#fff", + "primaryBorderColor": "#111720", + "lineColor": "#79B8FF", + "tertiaryColor": "#0d131b", + "tertiaryBorderColor": "#0d131b" + } +}}%% + +graph + +subgraph root + direction LR + count --> text --> effect1 & effect2 +end +``` + +Deriving a source in this manner is similar to creating an effect to update +another source. You should avoid doing this using an effect however. +Improper usage could accidently create infinite loops in the reactive graph. +Always favour deriving when you need one source to update based on another +source.