Pet Hatching Framework | PART 1

So, I was browsing through dev forum and saw that not many systems like this are made so I decided to make it. Also I was bored. Also Going to be a ton of hr spams lol. First time making a tutorial like this so yes.



The system looks something like that and if you want to know how to make it, read this post ig,
Oh yea if you want to test it out for yourself you can play it here - Pet Hatching Framework - Roblox



Before I start

You should know…

  • Roblox Lua / Scripting
  • Roblox’s Services (Not all, just TweenService and RunService)
  • Use of modules (Using Modules to create main functions)
  • CFrames
    And other Stuff which I most definitely forgot about

Last Thing, This will be of two parts. One will contain the frame appearance and the egg hatching effect and the other will contain the inventory thing. Ok thanks


Lets Start shall we…

Leaderstats

So for the leaderstats, I will be sticking with one which is coins since i do not want to over complicate things.
Oh and for the dummies that do not know what this is, Its basically storing an Int value inside the player as its stats. It also appears on the right side of your screen.
To Start, Go ahead and make a script in ServerScriptService and call it whatever you want.

-- Variables --
local DS = game:GetService("DataStoreService")
local Players = game:GetService("Players")

local CoinsDataStore = DS:GetDataStore("CoinsDS")
local SM = require(script.PlayerStats)

Players.PlayerAdded:Connect(function(Player)
	local Coins = SM.AddPlayerStats(Player)
	
	local success, CoinData = pcall(function()
		return CoinsDataStore:GetAsync(Player.UserId)
	end)
	Coins.Value = (type(CoinData) == "number" and CoinData) or 0
	
	while wait(2) do
		Coins.Value += 50
	end
end)

Players.PlayerRemoving:Connect(function(Player)
	local stats = Player.leaderstats
	local Coins = stats.Coins.Value

	CoinsDataStore:UpdateAsync(Player.UserId, function(oldData)
		return Coins
	end)
end)

Then make a module script inside the script and put this inside of it.
(Or i mean you just put it inside the server script but whatever, its easier to add more this way.)

local Stats = {}

function Stats.AddPlayerStats(Player)
	local Folder = Instance.new("Folder", Player)
	Folder.Name = "leaderstats"
	
	local Coins = Instance.new('IntValue',Folder)
	Coins.Name = "Coins"
	
	return Coins
end

return Stats

A quick summary of this script does,
Basically its storing an int value in the player, and using datastores saves the players coins every time they leave.
Note - This Will Only Work On Studio If You Enable Datastore Access to Studio

Pet Making Time

Lets do something more fun.
We will set up all the props then script it to work which is something i like to do first.
So For the egg container I literally yeeted it out of an old project. There are a few important things you need to do however.
image
Suppose this is my egg, Keep all the decorative parts inside the Egg_Container and Keep the Egg mesh part (It will be important later on) outside that model.
Add a part inside the Egg and name it UI, and keep it outside the Egg_Container Folder too (basically the part will help use on the egg shops frame position.)
As for the position, just move it inside the egg and your good!
image

Then inside the Entire egg models Properties, add a number value attribute and call it Price - which will be the eggs price

image.

Pet Time

So for pet models, you can make them in blender but I was lazy so I did not and just used the pet pack.
If you want a specific one, you can go ahead and use the one by @LuaBearyGood
Its a great pack containing of actually good pet models which you can use here and I highly recommend go checking it out - Pet Pack Devforum Post
Those pets were already Welded, Tho i changed a few things of it, Heres an example.
For Instance, Lets use this shark pet as an example

image

If we open its workspace, we see that it has quite some parts. The ones marked by red are all welded to the head, while the ones in blue are not (which is just main).
You can name the other parts anything you want just keep Head as Head and Main as Main (Main will be mentioned more in a bit ). Every Part in the pet should NOT be anchored And CanCollide should be false (unless you want your pet trying to enter your character )
Quick Tip - If you want to weld it all to the head, use moon animators weld in place feature, which is very useful in this situation

image

Also Head here being the center of the pet

image

Next we make this part called Main which is basically a normal roblox studio part
which should cover about the entire head of the pet.

Main should be anchored and also set to Cancollide false and Transparency to 1.

image

Lastly we add a weld Constraint to main, Where part0 is set to Main and part1 is set to the Head. Your pet Explorer should be looking like this

image

I wont be explaining why we are doing this or this post will be way to long, tho if you really want to know why i can do it on dms or down in the reply section.

After your done making your pets, make a folder in replicated storage called Pets and parent your pet to it


Indexs

Great My pets and Eggs are all made and ready to be used!

image

Now that we go those out of the way, lets start making our modules!

So I made a modules folder containing 2 more folders which are EggModules and PetModules. Right lets get started on making our index’s
This is just our pets Names, stats being declared in a script which will be used later on! So open a module script called Pet Index and parent it to pet modules
It should be looking something like this

local Rarities = {
		WaterEgg = {
			{
				Name = "Shark",
				Rarity = "Common",
				Chance = 50,
			},
			
			{	Name = "AquaDragon",
				Rarity = "Uncommon",
				Chance = 35,
			},
			
			{	
				Name = "Babylightning",
				Rarity = "Rare",
				Chance = 10,
			},
			
			{
				Name = "BacterialVirus",
				Rarity = "Mythic",
				Chance = 5,
			},
			
		},
		
	["FireEgg"] = {
		{
			Name = "SmallDemon",
			Rarity = "Common",
			Chance = 55,
		},
		{    
			Name = "Demon",
			Rarity = "Uncommon",
			Chance = 30,
		},
		{    
			Name = "DemonDominus",
			Rarity = "Rare",
			Chance = 10,
		},
		{    
			Name = "Ultimus",
			Rarity = "Mythic",
			Chance = 5,
		},
	},
}

	return Rarities

This will help us get the stats of each pet and also know which egg they belong too!

Lets also make an Egg Index module under Egg Modules, which will help use get the data for the eggs. It should be something like this

local Data = {}
local EggData = {}
local PetIndex = require(script.Parent.Parent.PetModules.PetIndex)
local Eggs = workspace:WaitForChild("Eggs")

function EggData.GetEgg(EggName)
	if not Data[EggName] then
		local Egg = Eggs:FindFirstChild(EggName)
		local Data = PetIndex[EggName]

		if Data then
			local Chance = 0
			for _, pet in pairs(PetIndex[EggName]) do
				Chance += pet.Chance
			end
			EggData[EggName] = {
				Name = EggName,
				Price = Egg:GetAttribute("Price"),
				PetData = Data,
				TotalChance = Chance  
			}
			return EggData[EggName]
		end
	end
end

return EggData

This is important as its gonna help us to obviously get the egg data. Small explaination of this script:
First we create the function Get Egg passing the parameter Egg Name, we check if Egg Name is not there, and then define data as pet index. Then using Data[EggName] we get the Name, Price of the Egg along with the chance and Pet Data of the pets!
Cool! (Jeez this sounds like a ramble instead of a tutorial, forgive me.)

Pet Frame Thing :sweat:

Basically the frame is the pop-up that comes when you come close to the egg cointainer. (Low quality image ahhhh.)

image

This part will take a while since it has 4 scripts which need more modules etc. But basically this is the big part.

Ok so first things first insert

  • Create a Screen Gui in Starter GUI and call it EggHatch
Insert a Number Value, Call it FarthestDistance and keep it in the Screen Gui
Add a String Value called CurrentEgg and keep in under the Screen Gui.

Ok lets start scripting.

Every script from now will be a local script as it will affect only the local player and not everybody else in the game.

So Create a local script called FrameHandler and paste the following code.

local Player = game.Players.LocalPlayer
local RS = game:GetService("RunService")
local Cam = workspace.Camera

local Frame = script.Parent.PurchaseMenu
local FrameSize = Frame.Size
local MaxDistance = script.Parent.FarthestDistance
local Eggs = workspace.Eggs:GetChildren()
local ChosenEgg = script.Parent.CurrentEgg
local Slot = Frame.SlotBackground.Slots
local Amount = Frame.AmountBackground.AmountBackground.CurrencyIcon.Cost
local EggIndex = require(game.ReplicatedStorage.Modules.EggModules.EggIndex)

local HatchingValue = game.ReplicatedStorage.Values.Hatching
local character = Player.Character or Player.CharacterAdded:Wait()
local Hrp = character:WaitForChild("HumanoidRootPart")

local function GetClosestEgg(CurrentEgg, HRP)
	local closest
	local currentClosest = MaxDistance.Value
	for _, Eggs in ipairs(CurrentEgg) do
		local distance = (Eggs.UI.Position - HRP.Position).Magnitude
		if distance <= currentClosest then
			currentClosest = distance
			closest = Eggs
		end
	end
	return closest
end

RS.RenderStepped:Connect(function()
	if not Hrp:IsDescendantOf(workspace) then
		character = Player.Character or Player.CharacterAdded:Wait()
		Hrp = character:WaitForChild("HumanoidRootPart")
	end
	
	if HatchingValue.Value == false then
	local camRatio =((Cam.CFrame.Position - Cam.Focus.Position).Magnitude)/11
	local availableEggs = {}

		for _, Egg in ipairs(Eggs) do
			if Egg:IsA("Model") then
				if (Egg.UI.Position - 	Hrp.Position).Magnitude <= MaxDistance.Value then
					table.insert(availableEggs, Egg)
				end
			end
		end

		local closestEgg
		if #availableEggs < 1 then
			Frame.Visible = false
			ChosenEgg.Value = "None"
			return
		elseif #availableEggs == 1 then
			closestEgg = availableEggs[1]

		elseif #availableEggs > 1 then
			closestEgg = GetClosestEgg(availableEggs, Hrp)
		end

	if closestEgg then
			ChosenEgg.Value = closestEgg.Name

			local worldScreenPoint = Cam:WorldToScreenPoint(closestEgg.UI.Position)
			Frame.Visible = true

			Frame.Position = UDim2.fromOffset(worldScreenPoint.X, worldScreenPoint.Y)
			Frame.Size = UDim2.new(FrameSize.X.Scale/camRatio, FrameSize.X.Offset, FrameSize.Y.Scale/camRatio, FrameSize.Y.Offset)
		end
	end
end)

HatchingValue:GetPropertyChangedSignal("Value"):Connect(function()
	local Value = HatchingValue.Value
	if Value then
		Frame.Visible = false
	else
		Frame.Visible = true
	end
end)

Quick Overview - It makes sure that the player is in a certain radius of the egg and then makes the frame visible and gives us the egg data.

Oh yea lets make the gui that shows up for the egg.
This is how i have made mine

image

And here’s the explorer tab for it.

And the final result of this script

Ah yes but it looks so empty, and the price value of the eggs dont come up
Yes yes , I’m getting to that

Ok now lets make a new script called slot handler which adds the pets to the viewport frames inside the slot.

For reference - Slot Explorer

image

Ok so inside the local script slot, paste this script which handles the entire slot as well as frame data.

local Slot = script.Parent.PurchaseMenu.SlotBackground.Slots
local ChosenEgg = script.Parent.CurrentEgg
local Frame = script.Parent.PurchaseMenu
local EggIndex = require(game.ReplicatedStorage.Modules.EggModules.EggIndex)
local EggEffect = require(game.ReplicatedStorage.Modules.EggModules.EggEffect)
local Amount = Frame.AmountBackground.AmountBackground.CurrencyIcon.Cost
local EggName = Frame.NameBackground.Background.TextLabel

local function resetFrame()
	for _, slot in ipairs(Slot:GetChildren()) do
		for _, item in ipairs(slot.PetView:GetChildren()) do
			item:Destroy()
		end		
		slot.Chance.Text = ""
		slot.Rarity.Text = ""
	end
end

ChosenEgg:GetPropertyChangedSignal("Value"):Connect(function()
	if ChosenEgg.Value == "None" then
		resetFrame()
		Frame.Visible = false
	else 
		local Egg = EggIndex.GetEgg(ChosenEgg.Value)
		if Egg then
			resetFrame()
			Amount.Text = Egg.Price
			EggName.Text = Egg.Name
			Frame.Visible = true
			EggEffect.AddPets(Slot, Egg)
		end
	end
end)

Anyway you should have gotten an error saying
EggEffect Does not exist :c

So, lets create a new module called EggEffect and add it to the eggmodules folder.

Then go ahead and add this to it.

local TS = game:GetService("TweenService")
local RS = game:GetService("RunService")

local EggDataModule = require(game.ReplicatedStorage.Modules.EggModules:WaitForChild("EggIndex"))
local RarityColors = require(game.ReplicatedStorage.Modules.PetModules.PetRarityColors)

-- Effects --
local Blur = game.Lighting.Blur
local EF = workspace:WaitForChild("Eggs")
local Pets = game.ReplicatedStorage.Pets

local EggViewportHandler = {}

function EggViewportHandler.AddPets(slots, Egg)
	for i, pet in pairs(Egg.PetData) do
		local petClone = Pets:FindFirstChild(pet.Name):Clone()
		local currentSlot = slots:FindFirstChild("Slot" .. i)
		local Color = RarityColors[pet.Rarity]

		local viewport = currentSlot.PetView
		local camera = Instance.new("Camera", viewport)
		viewport.CurrentCamera = camera

		petClone:SetPrimaryPartCFrame(CFrame.new(0, 0, 0))
		petClone.Parent = viewport

		currentSlot.Chance.Text = pet.Chance .. "%"
		currentSlot.Rarity.Text = pet.Rarity
		currentSlot.Rarity.TextColor3 = Color

		coroutine.wrap(function()
			local Rotation = 0
			local distance = petClone.PrimaryPart.Size.Z

			while petClone.Parent do
				camera.CFrame = CFrame.Angles(0, math.rad(Rotation), 0) * CFrame.new(Vector3.new(0, 0, distance), Vector3.new(0, 0, 0))
				Rotation += 0.5
				RS.RenderStepped:Wait()
			end
		end)()
	end
end

Oh and if you get an error that rarity colors isnt existing or blur dosent exist. You can remove those lines as those will be used later on in the script. Otherwise if you really want to put it then add a Module script called PetRarityColors in the Petmodules folder and paste this script.

local PetRarityColors = {
	
	Common = Color3.fromRGB(85, 255, 127),
	Uncommon = Color3.fromRGB(223, 201, 34),
	Rare = Color3.fromRGB(255, 47, 47),
	Mythic = Color3.fromRGB(211, 79, 255),
}

return PetRarityColors

Its basically helping us get the colors for the rarities.
Dont Forget to add Blur to lighting for this to not give errors k thx

Anyway if you did it right, if should work like this.

image


If you reached all the way here, give yourself a pat on your back. Good Job!


Ok now alot of this next code is going to be the back end except like the effect. The scripts left are
  • The Egg Purchase
  • The Egg Purchase Check script
  • Random Pet Choosing
  • The Hatch Event
  • The Egg Effect

Egg Purchase Check

``
Import a module script called EggPurchaseCheck in EggModules and paste the following Code

local EggIndex = require(script.Parent:WaitForChild("EggIndex"))

local EggPurchaseModule = {}

function EggPurchaseModule.Check(player, eggName, amount, eggdata)
	local price
	if eggdata then
		price = eggdata.Price
	else
		price = EggIndex.FindEgg(eggName)
	end

	if price then
		local PlayerCoinStats = player.leaderstats:FindFirstChild("Coins")
		local Check = false

		repeat
			if PlayerCoinStats.Value >= price * amount then
				Check = true
				PlayerCoinStats.Value -= price
			else
				amount -= 1
			end
		until (amount < 1) or Check

		if Check then
			return (eggdata and amount) or true
		else
			return print(player.Name .. " Has insufficient funds!")
		end
	else
		return print("Could not find price of " .. eggName)
	end
end

return EggPurchaseModule

This will record the players egg purchase and will be used in the main server script.

Egg Purchase Script

This script will do 2 things.
Checking the player has bought the egg with the above module.
And if bought, will fire the Hatch remote event. So in Replicated storage Add 2 folders, Namely - Remotes And Values.
Add a remote event Called EggOpen in Remote.
Add a Number Value In Values Called EggOpenCooldown and Bool Value Called Hatching.

image

Ok, now lets make the egg purchase script so add a script to server script service and paste the following code.

-- Services --
local Player = game:GetService("Players")
local RS = game:GetService("ReplicatedStorage")

-- Modules --
local EggHandler = require(RS.Modules.EggModules.EggHandler)

-- Remotes --
local HatchEvent = RS.Remotes.EggOpen

-- Controllers --
local cooldowns = {}
local CooldownValue = game.ReplicatedStorage.Values.EggOpenCooldown

local function hatch(player, eggName)
	if not cooldowns[player] then
		cooldowns[player] = time()
	end
	
	if time() >= cooldowns[player] then
		cooldowns[player] = time() + CooldownValue.Value
	
		local newPets = EggHandler.Purchase(player, eggName, 1)
		HatchEvent:FireClient(player, newPets, eggName)
	end 
end

HatchEvent.OnServerEvent:Connect(hatch)

Random Pet Choosing

Ok so you must have seen that in the script above the EggHandler module is called.
That script is the random pet choosing script.
So make a module script called EggHandler in EggModules and put this code that will make the random value for pets work


local EggData = require(script.Parent.EggIndex)
local EggPurchaseCheck = require(script.Parent.EggPurchaseCheck)

local function RandomPet(pets, Chance)
	
	local luck = math.random(Chance)
	for _, pet in ipairs(pets) do
		if luck > pet.Chance then
			luck -= pet.Chance
		else
			return pet.Name, pet.Rarity
		end
	end
end


local EggPurchaseHandler = {}

function EggPurchaseHandler.Purchase(Player, EggName, Amount)
	
	local Egg = EggData.GetEgg(EggName)
	
	local canBuy = EggPurchaseCheck.Check(Player, EggName, Amount, Egg)
	
	if canBuy then
		local newPets = {}
		
		repeat
			local newPet, petRarity = RandomPet(Egg.PetData, Egg.TotalChance)
			table.insert(newPets, {Name = newPet, Rarity = petRarity, EggName = Egg})
		until #newPets >= Amount
		
		return newPets
	end
end

return EggPurchaseHandler

Ok Almost every module script is completely done except the Egg Effect which we will do last.

The Hatch Event

So as you can see we fired the even from the server script. Next we need to mention what the event does when it is fired.
So add a local script to the EggHatch Screen Gui and call it Hatch Handler.

local Player = game:GetService("Players").LocalPlayer
local CAS = game:GetService("ContextActionService")

local EggPurchase = require(game.ReplicatedStorage.Modules.EggModules.EggPurchaseCheck)
local EggIndex = require(game.ReplicatedStorage.Modules.EggModules.EggIndex)
local EggEffect = require(game.ReplicatedStorage.Modules.EggModules.EggEffect)

local Frame = script.Parent.PurchaseMenu
local buttons = Frame.Buttons
local Ebutton = buttons.E.Button

local hatchEvent = game.ReplicatedStorage.Remotes.EggOpen
local eggs = workspace.Eggs
local chosenEgg = script.Parent.CurrentEgg

local Cooldown = game.ReplicatedStorage.Values.EggOpenCooldown
local cooldown = time()
local Hatching = game.ReplicatedStorage.Values.Hatching

local function hatch(_ , inputState, inputObject)
	if inputState == Enum.UserInputState.Begin and time() >= cooldown and Hatching.Value == false then
		cooldown = time() + Cooldown.Value
			local EggData = EggIndex.GetEgg(chosenEgg.Value) 
			local result = EggPurchase.Check(Player, chosenEgg.Value, 1,EggData)
			if result then
			Hatching.Value = true
			hatchEvent:FireServer(chosenEgg.Value, false)
		end
	end
end

chosenEgg:GetPropertyChangedSignal("Value"):Connect(function()
	local Egg = chosenEgg.Value 
	if Egg ~= "None" then
		CAS:BindAction("Hatch", hatch, false, Enum.KeyCode.E)
	else
		CAS:UnbindAction("Hatch")
	end
end)

Ebutton.MouseButton1Up:Connect(function()
	hatch(nil, Enum.UserInputState.Begin, Enum.KeyCode.E)
end)

This will control when it supposed to reach the server. (like pressing E and being close to the egg.)

And add the Final local script to the EggHatch Screen gui and call it EggHatch lol.
Then Add this

local hatchevent = game.ReplicatedStorage.Remotes.EggOpen
local Hatching = game.ReplicatedStorage.Values.Hatching
local EggEffect = require(game.ReplicatedStorage.Modules.EggModules.EggEffect)

hatchevent.OnClientEvent:Connect(function(newPets, eggName)
	local NewFrame = script.Parent.Parent.Hatch.HatchFrame:Clone()
	NewFrame.Parent = script.Parent.Parent.HatchGui
	script.Parent.PurchaseMenu.Visible = false
	EggEffect.HatchPets(newPets, NewFrame, eggName)
	Hatching.Value = false
end)

This is basically the hatching part after you press e and have sufficient coins.

And GG your done with everything except the Egg Effect which is the last thing

Egg Effect

Oh boy, this is gonna take a while since this part is a little big.
In the EggEffect Module Add copy this entire function bellow the AddPets Function

local function TweenEgg(Obj,t,s,d, Props)
	return TS:Create(Obj,TweenInfo.new(t,s,d,0,false,0),Props)
end

-- Basically Tweening the Rotation of the Egg.
local function RotateEgg(egg, rotation, t)
	
	local Cframe = CFrame.new(egg.Position) * CFrame.Angles(0, 0, math.rad(rotation))

	local rotateTween = TweenEgg(egg, t , Enum.EasingStyle.Linear,Enum.EasingDirection.In, {CFrame = Cframe})
	rotateTween:Play()
	rotateTween.Completed:Wait()
	rotateTween:Destroy(); rotateTween = nil
end

local positions = {
	{Rotation = math.rad(0), Cframe = CFrame.new(0, -10, 0)},
	{Rotation = math.rad(45), Cframe = CFrame.new(-4.5, -10, 0)},
	{Rotation = math.rad(-45), Cframe = CFrame.new(4.5, -10, 0)},
}

function EggViewportHandler.HatchPets(newPets, HatchFrame, EggName)
	Blur.Size = 26
	Blur.Enabled = true

	local camera = Instance.new("Camera", HatchFrame)
	camera.CFrame = CFrame.new(0, 0, 6)
	HatchFrame.CurrentCamera = camera

	local numberOfPets = #newPets
	local petsHatched = 0

	for i, v in ipairs(newPets) do
		coroutine.wrap(function()
			local petName = v.Name
			
			local rarity = v.Rarity

			local Pet = Pets:FindFirstChild(petName, true):Clone()
			local Egg = EF:FindFirstChild(EggName).Egg:Clone()
			
			local Rotation = (numberOfPets > 1 and positions[i].Rotation) or positions[3].Rotation/2
			local cframe = positions[i].Cframe

			Egg.Parent = HatchFrame
			Egg.CFrame = cframe

			local liftEggTween = TweenEgg(Egg, 0.65, Enum.EasingStyle.Quad,Enum.EasingDirection.In, {Position = Egg.Position + Vector3.new(0, 10, 0)})
			liftEggTween:Play()
			liftEggTween.Completed:Wait()
			liftEggTween:Destroy(); liftEggTween = nil

			local delayTime = 0.11
			
			for inc = 1, 10 do
				RotateEgg(Egg, -15, delayTime)
				RotateEgg(Egg, 15, delayTime)

				delayTime -= 0.007
				
			end

			RotateEgg(Egg, 0, delayTime)

			local flashEffect = HatchFrame["1"].FlashEffect
		--	flashEffect.ImageColor3 = (rarity ~= "Common") or flashEffect.ImageColor3

			local flash = TweenEgg(flashEffect, 0.2 , Enum.EasingStyle.Linear,Enum.EasingDirection.Out, {ImageTransparency = 1, Size = UDim2.new(1.5, 0, 1.5, 2)})
			flash:Play()
			flash.Completed:Wait()
			flash:Destroy(); flash = nil

			Pet.Parent = HatchFrame
			Pet:SetPrimaryPartCFrame(CFrame.new(0,0,0) * CFrame.Angles(0, 1.35, 0))
			Egg:Destroy()
			local Color = RarityColors[v.Rarity]

			HatchFrame[i].PetName.Text = petName
			HatchFrame[i].PetRarity.Text = rarity
			HatchFrame[i].PetRarity.TextColor3 = Color
			
			wait(1)

			local size = Blur.Size/10
			for i = 1, 10 do
				Blur.Size -= size
				wait(0.05)
			end
			
			HatchFrame[i].PetName.Text = ""
			HatchFrame[i].PetRarity.Text = ""

			petsHatched += 1
			print("You hatched a " .. petName)
		end)()
	end

	repeat
		RS.RenderStepped:Wait()
	until petsHatched >= numberOfPets

	local lowerFrameTween = TweenEgg(HatchFrame, 0.2, Enum.EasingStyle.Quad,Enum.EasingDirection.Out, {Position = UDim2.fromScale(0, 1)})
	lowerFrameTween:Play()
	lowerFrameTween.Completed:Wait()
	lowerFrameTween:Destroy()
	lowerFrameTween = nil

	HatchFrame:Destroy()
	
end

This is the entire egg Effect Which will make the egg tween up , rotate , open and then tween back down.
I suggest actually reading the entire script so its easier to understand and know whats up but yea heres the entire framework for part 1.


If you have any questions / comments or any sort of criticism for this post, tell me bellow. This is my first or second community resource and ill be glad to know what i can work on. Thank you so much and have a wonder full day!

49 Likes

can you please make part two where its has inventory and equipt best and unequipt all button

How would I be able to include pets with a decimal percentage? We’re using math.random to choose our luck number, which is unable to print decimals. Let’s say our total chance adds up to 2.5 (1%, 1%, 0.5%), it would be impossible to hatch the 0.5% pet. Any ideas? Much appreciated.

Update: I was able to find a solution to this.

local function RandomPet(pets, Chance, Division) 
	
	local luck = math.random(Chance*10000)  --decimal spaces (in my case 0.0005)
	local realLuck = luck/10000 -- convert luck to it's decimal number
	print(realLuck) 
	for _, pet in ipairs(pets) do 
		if realLuck > pet.Chance then 
			realLuck -= pet.Chance 
		else
			return pet.Name, pet.Rarity, pet.Chance
		end
	end
end

This should solve this problem for anyone else who was wondering how to do so.

6 Likes

working on a part 2 for this. I got the motivation finally!

4 Likes

Can you please add a video showing the final result?

There’s a video at the top of the post showing the final result as well as the place file

Oh, I didn’t notice it. Sorry!

That’s incredibelly useful. Thanks!

For the next parts, you could do these ideas :

  • Pet Boost (Gives more coins)
  • Inventory
  • Equip / Unequip Button
  • Delete Button
  • Rename Pet System
1 Like

The pet boost is actually quite easy. I suggest making a separate datastore for your pets (optional) and add it to a dictionary A.K.A your pets inventory every time you purchased an egg, although duping is a problem so I suggest making a session locking system for your datastore or using ProfileService. Then for the pet boost, get the equipped pets you have and get their “boost” data if they have and do your own math for calculating the boost they give. Deleting pets should be easy because you just have to remove them from the table you store your pets in. I’m too lazy to write other stuff so just wait for Part 2 of this! :smile:

1 Like

There is no Place File @Shrinebloxian
???

so, i was done doing egg effect script, then i wanted to test it but when i tested it it just said:
image

Hello, I had the same error and I fixed it by adding “return EggViewportHandler” at line 43.

local TS = game:GetService("TweenService")
local RS = game:GetService("RunService")

local EggDataModule = require(game.ReplicatedStorage.Modules.EggModules:WaitForChild("EggIndex"))
local RarityColors = require(game.ReplicatedStorage.Modules.PetModules.PetRarityColors)

local Blur = game.Lighting.Blur
local EF = workspace:WaitForChild("Eggs")
local Pets = game.ReplicatedStorage.Pets

local EggViewportHandler = {}

function EggViewportHandler.AddPets(slots, Egg)
	for i, pet in pairs(Egg.PetData) do
		local petClone = Pets:FindFirstChild(pet.Name):Clone()
		local currentSlot = slots:FindFirstChild("Slot" .. i)
		local Color = RarityColors[pet.Rarity]

		local viewport = currentSlot.PetView
		local camera = Instance.new("Camera", viewport)
		viewport.CurrentCamera = camera

		petClone:SetPrimaryPartCFrame(CFrame.new(0, 0, 0))
		petClone.Parent = viewport

		currentSlot.Chance.Text = pet.Chance .. "%"
		currentSlot.Rarity.Text = pet.Rarity
		currentSlot.Rarity.TextColor3 = Color

		coroutine.wrap(function()
			local Rotation = 0
			local distance = petClone.PrimaryPart.Size.Z

			while petClone.Parent do
				camera.CFrame = CFrame.Angles(0, math.rad(Rotation), 0) * CFrame.new(Vector3.new(0, 0, 0), Vector3.new(0, 0, 20))
				Rotation += 0.5
				RS.RenderStepped:Wait()
			end
		end)()
	end
end

return EggViewportHandler

Explaination : require() is used to call a module in a script and it takes the return value of a module script. But in that case we didn’t return any values from the module script “EggEffect” so we have to take the function name as a return value, so the script can run the proper function.

Hope it helped!

So basically an error pops up: HatchFrame is not a member of PlayerGui.Hatch

In the tutorial you never told us about making a hatch gui so im confused on what to do next.

4 Likes

Post flagged, you simply don’t know what your doing which is why you incorrectly believe it to be bad. Educate yourself on the topic a bit more and then you might be able to understand it.

i know what im doing and i’ve already acomplished what i needed, its not that his skills are bad, its just the tutorial (the displaying of how to do things) is bad

For anybody still using this tutorial, I’ve uncopylocked the game so you can just grab the system. The majority of this three-year-old tutorial is still functional, but I think I could have done a Much better job of explaining the framework. Although I doubt I’ll be editing this, if I do write a new post, I’ll definitely organize it much better.

@yaemiza Thanks for pointing it out!

1 Like

Is there a part 2 already made to this tutorial?