Module Scripts Not Working

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 :slight_smile:

2 Likes

bump

Hi, I would recommend that you use ProfileService for storing data. Stick to recreating the deep plate, if that is what you want, but ProfileService handles all your datastoring really nicely.

Which “Substract” function are you referring to? I couldn’t find it by looking quickly over your code.

What do you mean by the pets doesn’t show up on join?

The module named “followModule.unEquip” is what I meant, sorry if I was not clear about that lol. What I mean when I say the pets do not show up on join is that the models do not load in when the player joins.