So I kinda messed up… I was writing my script for a while now and then I realized other players are unable to see the cloned pet (I’m cloning them through the local script)
local marketplaceService = game:GetService("MarketplaceService")
local runService = game:GetService("RunService")
local player = game.Players.LocalPlayer
local blackToothless = game.ReplicatedStorage.DragonCompanion
local button = script.Parent
local blackToothlessClone = nil
local isPetEquipped = false
local gamepassId = 719413770 -- Replace with the ID of your gamepass
-- Function to update button text based on gamepass ownership
local function UpdateButtonText()
local ownsGamepass = marketplaceService:UserOwnsGamePassAsync(player.UserId, gamepassId)
button.Text = ownsGamepass and "Equip" or "Purchase"
end
-- Immediately update button text when the script runs
UpdateButtonText()
local function UpdatePetPosition()
while isPetEquipped do
if blackToothlessClone and player.Character then
if (blackToothlessClone.HumanoidRootPart.Position - player.Character.HumanoidRootPart.Position).Magnitude <= math.huge then
local newPosition = player.Character.HumanoidRootPart.Position + Vector3.new(5, 3, 5)
blackToothlessClone.HumanoidRootPart.CFrame = blackToothlessClone.HumanoidRootPart.CFrame:Lerp(CFrame.new(newPosition), 0.05)
local lookAtPosition = player.Character.HumanoidRootPart.Position
local lookRotation = CFrame.new(blackToothlessClone.HumanoidRootPart.Position, lookAtPosition)
local initialRotationOffset = CFrame.Angles(0, math.rad(-90), 0)
lookRotation = lookRotation * initialRotationOffset
blackToothlessClone.HumanoidRootPart.CFrame = lookRotation * CFrame.new(0, 0, 0)
end
end
runService.RenderStepped:Wait()
end
end
local function ClonePet()
local ownsGamepass = marketplaceService:UserOwnsGamePassAsync(player.UserId, gamepassId)
if not ownsGamepass then
-- Prompt the purchase of the gamepass
marketplaceService:PromptGamePassPurchase(player, gamepassId)
return -- Stop execution if the player doesn't own the gamepass
end
if blackToothlessClone then -- Check if the pet has already been cloned
-- Destroy the pet if it already exists
blackToothlessClone:Destroy()
blackToothlessClone = nil -- Reset the variable
button.Text = "Equip" -- Change button text to "Equip"
isPetEquipped = false
else
-- Check if the player's pet folder already exists
local playerFolderName = player.UserId .. "_Pet"
local existingFolder = game.Workspace:FindFirstChild(playerFolderName)
if existingFolder then
-- If the folder already exists, use it to parent the pet
blackToothlessClone = blackToothless:Clone()
blackToothlessClone.Parent = existingFolder
else
-- If the folder doesn't exist, create a new one
local playerFolder = Instance.new("Folder")
playerFolder.Name = playerFolderName -- Use the player's UserId to make it unique
playerFolder.Parent = game.Workspace
blackToothlessClone = blackToothless:Clone()
blackToothlessClone.Parent = playerFolder
end
-- Set the pet's position close to the player
if player.Character then
blackToothlessClone:SetPrimaryPartCFrame(CFrame.new(player.Character.HumanoidRootPart.Position))
end
button.Text = "Unequip" -- Change button text to "Unequip"
isPetEquipped = true
UpdatePetPosition()
end
end
script.Parent.MouseButton1Click:Connect(function()
ClonePet()
end)
marketplaceService.PromptGamePassPurchaseFinished:Connect(function(player, passId, wasPurchased)
if passId == gamepassId and wasPurchased then
print(player.Name .. " successfully purchased the gamepass. Granting particles.")
UpdateButtonText()
end
end)
If someone could split the code in LocalScript + ServerScript or instead make the pet visible to others, I’d appreciate it.
What I think you’ll need to do is to use Remote Events. Store a Remote Event in ReplicatedStorage and create a server script into ServerScriptService.
-
Server Script
game:GetService(“ReplicatedStorage”).RemoteEvent.OnServerEvent:Connect(function(player)
[The ClonePet() Script]
end)
-
Local Script
script.Parent.MouseButton1Click:Connect(function()
game:GetService(“ReplicatedStorage”).RemoteEvent:FireServer()
end)
You want to also add one for the UpdatePetPosition.
Also, remember to edit the GUI using “Player.PlayerGui” when you transfer the script to server script.
ServerSide
local MarketplaceService = game:GetService("MarketplaceService")
local ServerStorage = game:GetService("ServerStorage")
local PetReplicator = game.ReplicatedStorage:WaitForChild("PetReplicator")
local blackToothless = ServerStorage.DragonCompanion
local gamepassId = 719413770 -- Replace with the ID of your gamepass
local function CreatePet(player)
local ownsGamepass = MarketplaceService:UserOwnsGamePassAsync(player.UserId, gamepassId)
if not ownsGamepass then
return -- Player doesn't own the gamepass, don't create the pet
end
local playerFolderName = player.UserId .. "_Pet"
local existingFolder = game.Workspace:FindFirstChild(playerFolderName)
if not existingFolder then
existingFolder = Instance.new("Folder")
existingFolder.Name = playerFolderName
existingFolder.Parent = game.Workspace
end
local pet = blackToothless:Clone()
pet.Parent = existingFolder
return pet
end
PetReplicator.OnServerEvent:Connect(function(player)
local pet = CreatePet(player)
if pet then
-- Position the pet close to the player
local character = player.Character
if character then
pet:SetPrimaryPartCFrame(CFrame.new(character.HumanoidRootPart.Position))
end
end
end)
LocalScript
local MarketplaceService = game:GetService("MarketplaceService")
local PetReplicator = game:GetService("ReplicatedStorage").PetReplicator
local player = game.Players.LocalPlayer
local button = script.Parent
local isPetEquipped = false
local gamepassId = 719413770 -- Replace with the ID of your gamepass
local runService = game:GetService("RunService")
local blackToothlessClone = nil
local function UpdateButtonText()
local ownsGamepass = MarketplaceService:UserOwnsGamePassAsync(player.UserId, gamepassId)
button.Text = ownsGamepass and "Equip" or "Purchase"
end
UpdateButtonText()
local function UpdatePetPosition()
while isPetEquipped do
if blackToothlessClone and player.Character then
local targetPosition = player.Character.HumanoidRootPart.Position + Vector3.new(5, 3, 5) -- Offset from the player's position
local distance = (blackToothlessClone.HumanoidRootPart.Position - targetPosition).Magnitude
if distance > 1 then -- Adjust this threshold as needed to prevent jittery movement
-- Interpolate the pet's position towards the target position
blackToothlessClone.HumanoidRootPart.CFrame = blackToothlessClone.HumanoidRootPart.CFrame:Lerp(CFrame.new(targetPosition), 0.05)
-- Make the pet face towards the player
local lookAtPosition = player.Character.HumanoidRootPart.Position
local lookRotation = CFrame.new(blackToothlessClone.HumanoidRootPart.Position, lookAtPosition)
local initialRotationOffset = CFrame.Angles(0, math.rad(-90), 0)
lookRotation = lookRotation * initialRotationOffset
blackToothlessClone.HumanoidRootPart.CFrame = lookRotation * CFrame.new(0, 0, 0)
end
end
runService.RenderStepped:Wait()
end
end
local function ClonePet()
local ownsGamepass = MarketplaceService:UserOwnsGamePassAsync(player.UserId, gamepassId)
if not ownsGamepass then
MarketplaceService:PromptGamePassPurchase(player, gamepassId)
return
end
if not isPetEquipped then
PetReplicator:FireServer() -- Request the server to create the pet
button.Text = "Unequip"
else
button.Text = "Equip"
-- You might want to remove the pet from the client's view here
-- Since the pet is managed by the server
end
isPetEquipped = not isPetEquipped
end
button.MouseButton1Click:Connect(ClonePet)
MarketplaceService.PromptGamePassPurchaseFinished:Connect(function(player, passId, wasPurchased)
if passId == gamepassId and wasPurchased then
print(player.Name .. " successfully purchased the gamepass. Granting particles.")
UpdateButtonText()
end
end)
PetReplicator.OnClientEvent:Connect(function(pet)
blackToothlessClone = pet
if isPetEquipped then
-- Start updating the pet's position if it's equipped
UpdatePetPosition()
end
end)
I tried but uh… the pet won’t clone
Well, I think it is cloning but I think the issue is that you would also want to create another remote event for UpdatePetPosition().
Just put it in the same server script and give that a try!
Can I replicate the movement on the client-side with the LocalScript? The server should automatically update the position of the object if it was cloned globally.
I don’t think that would work, you probably want to just do the movement in a server script and get the model by cloning in the server script or else the local player will see the model and movement but other players won’t see it.
ServerSideScript
local MarketplaceService = game:GetService("MarketplaceService")
local PetReplicator = game:GetService("ReplicatedStorage"):WaitForChild("PetReplicator")
local PetPositionUpdater = game:GetService("ReplicatedStorage"):WaitForChild("PetPositionUpdater")
local playerPets = {}
local gamepassId = 719413770 -- Replace with the ID of your gamepass
local function CreatePet(player)
local ownsGamepass = MarketplaceService:UserOwnsGamePassAsync(player.UserId, gamepassId)
if not ownsGamepass then
return -- Player doesn't own the gamepass, don't create the pet
end
local playerFolderName = player.UserId .. "_Pet"
local existingFolder = game.Workspace:FindFirstChild(playerFolderName)
if not existingFolder then
existingFolder = Instance.new("Folder")
existingFolder.Name = playerFolderName
existingFolder.Parent = game.Workspace
end
local pet = game.ServerStorage.DragonCompanion:Clone()
pet.Parent = existingFolder
playerPets[player.UserId] = pet
return pet
end
local function UpdatePetPosition(player, isPetEquipped)
while isPetEquipped do
local pet = playerPets[player.UserId]
if pet and player.Character then
local targetPosition = player.Character.HumanoidRootPart.Position + Vector3.new(5, 3, 5) -- Offset from the player's position
local distance = (pet.HumanoidRootPart.Position - targetPosition).Magnitude
if distance > 1 then -- Adjust this threshold as needed to prevent jittery movement
-- Interpolate the pet's position towards the target position
pet.HumanoidRootPart.CFrame = pet.HumanoidRootPart.CFrame:Lerp(CFrame.new(targetPosition), 0.05)
-- Make the pet face towards the player
local lookAtPosition = player.Character.HumanoidRootPart.Position
local lookRotation = CFrame.new(pet.HumanoidRootPart.Position, lookAtPosition)
local initialRotationOffset = CFrame.Angles(0, math.rad(-90), 0)
lookRotation = lookRotation * initialRotationOffset
pet.HumanoidRootPart.CFrame = lookRotation * CFrame.new(0, 0, 0)
end
end
wait() -- Using wait instead of runService.RenderStepped:Wait() on the server
end
end
PetReplicator.OnServerEvent:Connect(function(player, destroyPet)
if destroyPet then
local pet = playerPets[player.UserId]
if pet then
pet:Destroy()
playerPets[player.UserId] = nil
end
else
local pet = CreatePet(player)
if pet then
-- Position the pet close to the player
local character = player.Character
if character then
pet:SetPrimaryPartCFrame(CFrame.new(character.HumanoidRootPart.Position))
end
end
end
end)
PetPositionUpdater.OnServerEvent:Connect(UpdatePetPosition)
LocalScript
local MarketplaceService = game:GetService("MarketplaceService")
local PetReplicator = game:GetService("ReplicatedStorage"):WaitForChild("PetReplicator")
local player = game.Players.LocalPlayer
local button = script.Parent
local isPetEquipped = false
local gamepassId = 719413770 -- Replace with the ID of your gamepass
local function UpdateButtonText()
local ownsGamepass = MarketplaceService:UserOwnsGamePassAsync(player.UserId, gamepassId)
button.Text = ownsGamepass and "Equip" or "Purchase"
end
UpdateButtonText()
local function ClonePet()
local ownsGamepass = MarketplaceService:UserOwnsGamePassAsync(player.UserId, gamepassId)
if not ownsGamepass then
MarketplaceService:PromptGamePassPurchase(player, gamepassId)
return
end
if not isPetEquipped then
PetReplicator:FireServer() -- Request the server to create the pet
button.Text = "Unequip"
else
-- Destroy the pet if it's already equipped
PetReplicator:FireServer(true) -- Request the server to destroy the pet
button.Text = "Equip"
end
isPetEquipped = not isPetEquipped
end
button.MouseButton1Click:Connect(ClonePet)
MarketplaceService.PromptGamePassPurchaseFinished:Connect(function(player, passId, wasPurchased)
if passId == gamepassId and wasPurchased then
print(player.Name .. " successfully purchased the gamepass. Granting particles.")
UpdateButtonText()
end
end)
The pet clones, but the position won’t update, it stays still.
Ugh, I give up. I’ll have to go sleep now and hopefully someone could help me out more by tomorrow.
Sorry, my mistake. When you clone the pet you would want to update its position after it’s been cloned.
One thing I would recommend is to not use remote events when updating the pet position since I only
see that you are using one pet. If this is also for multiple pets then if you want you can use a bindable function as an event function to put the cloned pet in the function like “Function:Invoke(pet)” and move the UpdatePetPosition in another server script just to keep things simple and tidy.
Just move the UpdatePetPostion() script under the CreatePet() so it won’t have a separate function for movement and make sure it’s under where the pet has been cloned where you create the variable for the cloned pet.
Also put “isPetEquipped” variable in the “PetReplicator:FireServer” brackets.
PetReplicator:FireServer(isPetEquipped)
local function CreatePet(player, isPetEquipped)
Remember to use your output to help and if that doesn’t then you can use print(“test”) to see where the problem occurs.