I am trying to use a module script in serverstorage and a module script in replicated storage for loading pets, but I am having some trouble.
Attached are the scripts I am using:
Replicated Storage Module Script:
local followModule = {}
--Constants
local PET_MODELS_FOLDER = game.ReplicatedStorage:FindFirstChild('Pets') -- Change to whatever the pet folder is
local MAX_PETS = 5 -- How many attachments there should be for pets
local DISTANCE_OF_PET = 3 -- Studs
local RESPONSIVENESS = 1000 --- How fast pet tweens to player
-- Variables
local petTable = {}
function followModule.addAttachments(character:Model, startingAmount: number?, equipedPetsTable: {string}?)
local humanoidRootPart:Part = character:FindFirstChild('HumanoidRootPart')
-- Delete all the previous attachments
startingAmount = startingAmount == nil and 0 or startingAmount
for i, value in ipairs(humanoidRootPart:GetChildren()) do
if value:IsA("Attachment") and string.match(value.Name, "petAttachment") then
value:Destroy()
end
end
for i = 0, startingAmount - 1, 1 do
local offset = (((startingAmount - 1) / 2) * DISTANCE_OF_PET) - (i * DISTANCE_OF_PET)
local attachment = Instance.new('Attachment')
attachment.Name = "petAttachment#"..(i+1)
attachment.Parent = humanoidRootPart
attachment.Position = Vector3.new(offset,1,5)
attachment.Orientation = humanoidRootPart.Orientation
end
end
function followModule.Refresh(character)
followModule.addAttachments(character, #petTable)
for i, v in ipairs(petTable) do
local petFollowModel:Model = PET_MODELS_FOLDER:FindFirstChild(v):Clone()
local a0 = character:FindFirstChild("HumanoidRootPart"):FindFirstChild("petAttachment#"..i)
petFollowModel.Parent = a0
local a1
for index, part: Part in ipairs(petFollowModel:GetDescendants()) do
if part:IsA('Part') then
if index == 1 then
a1 = Instance.new('Attachment')
a1.Parent = part
a1.Position = Vector3.new(0,0,0)
end
part.Anchored = false
part.CanCollide = false
end
end
if not a1 then
warn('no attachment 1')
return
end
local constraintPosition = Instance.new('AlignPosition')
constraintPosition.Parent = petFollowModel
constraintPosition.Attachment1 = a0
constraintPosition.Attachment0 = a1
constraintPosition.Responsiveness = RESPONSIVENESS
constraintPosition.MaxForce = 1000000
local constraintOrientation = Instance.new("AlignOrientation")
constraintOrientation.Parent = petFollowModel
constraintOrientation.Attachment1 = character:FindFirstChild("HumanoidRootPart"):FindFirstChild('orientationAttachmentManager')
constraintOrientation.Attachment0 = a1
constraintOrientation.Responsiveness = RESPONSIVENESS
constraintOrientation.MaxTorque = 1000000
end
end
function followModule.EquipPets(character:Model, petName:string)
local player = game.Players:GetPlayerFromCharacter(character)
petsNow = 1
if player:WaitForChild("Pets"):GetChildren() == nil then
petsNow = 1
else
petsNow = #player:WaitForChild("Pets"):GetChildren()
end
print(petsNow)
if not character:FindFirstChild("HumanoidRootPart"):FindFirstChild('orientationAttachmentManager') then
local orienAttachment = Instance.new('Attachment')
orienAttachment.Parent = character:FindFirstChild("HumanoidRootPart")
orienAttachment.Name = 'orientationAttachmentManager'
orienAttachment.Position = Vector3.new(0,0,0)
orienAttachment.Orientation = Vector3.new(0,90,0)
end
for _, attachment in ipairs(character:FindFirstChild("HumanoidRootPart"):GetChildren()) do
if attachment:IsA('Attachment') and string.match(attachment.Name, "petAttachment") then
local stringSplited = string.split(attachment.Name,'#')
petTable[tonumber(stringSplited[2])] = attachment:FindFirstChildWhichIsA("Model").Name
local name = attachment:FindFirstChildWhichIsA("Model").Name
end
end
if petsNow >= MAX_PETS then
warn("Cant equip anymore pets!!!")
return
else
table.insert(petTable, petName)
petsNow += 1
local a = script.PetExample:FindFirstChild(petName)
game.ReplicatedStorage:WaitForChild("Remotes").EquipPet:FireServer(a, petName)
followModule.Refresh(character)
end
end
function followModule.unEquip(character, pet: string)
for index, value in ipairs(petTable) do
if value == pet then
table.remove(petTable,index)
petsNow -= 1
print(petsNow)
game.ReplicatedStorage:WaitForChild("Remotes").UnequipPet:FireServer(pet)
followModule.Refresh(character)
break
end
end
end
return followModule
ServerStorage Module Script:
local followModule = {}
--Constants
local PET_MODELS_FOLDER = game.ReplicatedStorage:FindFirstChild('Pets') -- Change to whatever the pet folder is
local MAX_PETS = 5 -- How many attachments there should be for pets
local DISTANCE_OF_PET = 3 -- Studs
local RESPONSIVENESS = 1000 --- How fast pet tweens to player
-- Variables
local petTable = {}
function followModule.addAttachments(character:Model, startingAmount: number?, equipedPetsTable: {string}?)
local humanoidRootPart:Part = character:FindFirstChild('HumanoidRootPart')
-- Delete all the previous attachments
startingAmount = startingAmount == nil and 0 or startingAmount
for i, value in ipairs(humanoidRootPart:GetChildren()) do
if value:IsA("Attachment") and string.match(value.Name, "petAttachment") then
value:Destroy()
end
end
for i = 0, startingAmount - 1, 1 do
local offset = (((startingAmount - 1) / 2) * DISTANCE_OF_PET) - (i * DISTANCE_OF_PET)
local attachment = Instance.new('Attachment')
attachment.Name = "petAttachment#"..(i+1)
attachment.Parent = humanoidRootPart
attachment.Position = Vector3.new(offset,1,5)
attachment.Orientation = humanoidRootPart.Orientation
end
end
function followModule.Refresh(character)
followModule.addAttachments(character, #petTable)
for i, v in ipairs(petTable) do
local petFollowModel:Model = PET_MODELS_FOLDER:FindFirstChild(v):Clone()
local a0 = character:FindFirstChild("HumanoidRootPart"):FindFirstChild("petAttachment#"..i)
petFollowModel.Parent = a0
local a1
for index, part: Part in ipairs(petFollowModel:GetDescendants()) do
if part:IsA('Part') then
if index == 1 then
a1 = Instance.new('Attachment')
a1.Parent = part
a1.Position = Vector3.new(0,0,0)
end
part.Anchored = false
part.CanCollide = false
end
end
if not a1 then
warn('no attachment 1')
return
end
local constraintPosition = Instance.new('AlignPosition')
constraintPosition.Parent = petFollowModel
constraintPosition.Attachment1 = a0
constraintPosition.Attachment0 = a1
constraintPosition.Responsiveness = RESPONSIVENESS
constraintPosition.MaxForce = 1000000
local constraintOrientation = Instance.new("AlignOrientation")
constraintOrientation.Parent = petFollowModel
constraintOrientation.Attachment1 = character:FindFirstChild("HumanoidRootPart"):FindFirstChild('orientationAttachmentManager')
constraintOrientation.Attachment0 = a1
constraintOrientation.Responsiveness = RESPONSIVENESS
constraintOrientation.MaxTorque = 1000000
end
end
return followModule
Datastore script:
-- Services
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Instances
local DataStore = DataStoreService:GetDataStore("DataStore#01")
local Remotes = ReplicatedStorage.Remotes
local SetupInventoryGui = Remotes.SetupInventoryGui
local module = require(game.ServerStorage.ModuleScript)
-- Loading data
local function Load(player)
local PlayerData
-- Gets the player's data inside a secure function
local Success, Error = pcall(function()
PlayerData = DataStore:GetAsync(player.UserId)
end)
-- Kicks the player if there was an error loading the data
if not Success then
player:Kick("Error loading data: " .. Error)
end
-- Creates a new folder for the player's pets
local PetsFolder = Instance.new("Folder")
PetsFolder.Name = "Pets"
PetsFolder.Parent = player
-- If the player has got data (not first time playing) then
-- loop through all of their pets, creating a new value for it
if PlayerData then
for _, PetData in pairs(PlayerData) do
local Pet = Instance.new("BoolValue")
Pet.Name = PetData.Name
Pet.Value = PetData.Equipped
Pet.Parent = PetsFolder
end
end
-- Tells the client to setup the inventory. Call this in the local script
module.Refresh(player.Character)
SetupInventoryGui:FireClient(player)
end
-- Saving Data
local function Save(player)
local PetsFolder = player:FindFirstChild("Pets")
if not PetsFolder then
return -- The player hasn't created a pets folder, nothing will be saved
end
local PlayerData = {}
-- Looping through all of the player's pets
for _, Pet in pairs(PetsFolder:GetChildren()) do
-- Add the pet's name and value to the data, then add it to the main table
local Data = {
Name = Pet.Name,
Equipped = Pet.Value
}
table.insert(PlayerData, Data)
end
-- Save the main table in a secure function
pcall(function()
DataStore:SetAsync(player.UserId, PlayerData)
end)
end
-- Detect player's joining & leaving
Players.PlayerAdded:Connect(Load)
for _, Player in pairs(Players:GetPlayers()) do
Load(Player)
end
Players.PlayerRemoving:Connect(Save)
Pet Handler (In server script service):
local rems = game.ReplicatedStorage:WaitForChild("Remotes")
local rem1 = rems.EquipPet
local rem2 = rems.UnequipPet
rem1.OnServerEvent:Connect(function(player, a, petName)
local pet = a:Clone()
pet.Name = petName
pet.Parent = player:WaitForChild("Pets")
pet.Value = true
end)
rem2.OnServerEvent:Connect(function(player, pet)
player:WaitForChild("Pets"):WaitForChild(pet):Destroy()
end)
First: The Module Script in Replicated Storage’s subtract function does not work if the player joins the game at 5 pets
Second: The datastore saves and loads the values inside of the pet folder correctly, but the pets do not show up on join
If anyone knows how to fix these issues, I would be greatly appreciative ![]()