Seperate modules run only for latest joined player

Hi all, I’ve only starting working with module scripts recently, I don’t fully understand the extent of them, however, this problem has me stumped, to the point that I didn’t even know how to properly word this.

  1. What do you want to achieve? Keep it simple and clear!
    I’m making a game with multiple classes and different movesets, so I used modulescripts to have a simpler way to code in movesets, I clone the module and put it inside the player in a folder so it doesn’t require the same script.
  2. What is the issue? Include screenshots / videos if possible!
    Whenever a player joins after the first player, any inputs done by any other players is done by the latest joined player.
  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I tried looking for solutions to my problem already, but none of them were the solution.

Here are the scripts with the unimportant parts cut out
CombatManager Script:

function CharacterAdded(Character,Player)
	--// Set Class
	local State = StateTemplate
	repeat wait() until DataManager:GetClass(Player)
	local PlayerClass = DataManager:GetClass(Player)
	State["Class"] = PlayerClass
	--// Register Moves
	local MoveFolder = nil
	if not Player:FindFirstChild("MoveFolder") then
		MoveFolder = Instance.new("Folder")
		MoveFolder.Parent = Player
		MoveFolder.Name = "MoveFolder"
	end
	MoveFolder = Player:FindFirstChild("MoveFolder")
	MoveFolder:ClearAllChildren()
	local RegisteredMoves = {}
	local ClassFolder = Classes[PlayerClass]
	local StandardMoves = ClassFolder:WaitForChild("StandardMoves"):GetChildren()
	local BasicMoves = Classes:WaitForChild("BasicMoves"):GetChildren()
	for _, Move in pairs(BasicMoves) do
		local Module = Move:Clone()
		Module.Parent = MoveFolder
		local ReqModule = require(MoveFolder:FindFirstChild(Move.Name))
		RegisteredMoves[Move.Name] = ReqModule
		ReqModule:Init(Player)
		print(ReqModule.MovePlayer)
	end
	for _, Move in pairs(StandardMoves) do
		local Module = Move:Clone()
		Module.Parent = MoveFolder
		local ReqModule = require(MoveFolder:FindFirstChild(Move.Name))
		RegisteredMoves[ReqModule.MoveIndex] = ReqModule
		ReqModule:Init(Player)
		print(ReqModule.MovePlayer)
	end
	print(Player.Name)
	print(RegisteredMoves)
	
	local ClassPunchDamage = ClassFolder:WaitForChild("PunchDamage").Value
	RegisteredMoves["Punch"]:SetDamage(ClassPunchDamage)
	
	State["Moves"] = RegisteredMoves
	
	InitializeHumanoid(Character)

	--// Set State in Table
	PlayerStates[Player] = State
end
InputBegan.Event:Connect(function(Player : Player, Input)
	if KeycodesTable[Input] and PlayerStates[Player] then
		local PlayerState = PlayerStates[Player]
		local RegisteredMoves = PlayerState["Moves"]
		local MoveKey = KeycodesTable[Input]
		if RegisteredMoves[MoveKey] then
			local Move = RegisteredMoves[MoveKey]
			Move:Began()
		end
	end
end)

InputEnded.Event:Connect(function(Player : Player, Input)
	if KeycodesTable[Input] and PlayerStates[Player] then
		local PlayerState = PlayerStates[Player]
		local RegisteredMoves = PlayerState["Moves"]
		local MoveKey = KeycodesTable[Input]
		if RegisteredMoves[MoveKey] then
			local Move = RegisteredMoves[MoveKey]
			Move:Ended()
		end
	end
end)

Punch Module Script:

local Punch = {
		MoveName = "Punch",
	MoveCooldown = 0.45,
	MoveDamage = 2.5,
	Debounce = false,
	LeftJabAnim = script.LeftJab,
	RightJabAnim = script.RightJab,
	ElbowJabAnim = script.ElbowJab,
	LeftJabTrack = nil,
	RightJabTrack = nil,
	ElbowJabTrack = nil,
	MovePlayer = nil,
	Punching = false,
	ResetCooldown = 1,
	LastPunchTick = tick(),
	CurrentCombo = 0,
	PunchConnect = nil,
	Init = function(self,Player)
		self.MovePlayer = Player
		local Character = Player.Character
		local Humanoid = Character:WaitForChild("Humanoid")
		self.LeftJabTrack = Humanoid:LoadAnimation(self.LeftJabAnim)
		self.RightJabTrack = Humanoid:LoadAnimation(self.RightJabAnim)
		self.ElbowJabTrack = Humanoid:LoadAnimation(self.ElbowJabAnim)
	end,
	SetDamage = function(self,NewDamage)
		self.MoveDamage = NewDamage
	end,
	Began = function(self)
               -- long punch code that I won't put in because it's redundant to put here
	end,
	Ended = function(self)
		 -- stops punching.
	end,
}

return Punch

Here are the directories for the scripts above:
image
image

I hope I made my problem understandable enough, if you have any questions please ask away.

Edit 1: Added some more code and directories that I forgot to add last night that would hopefully make the issue more clear.

2 Likes

I think I know your issue, though I’m not fully sure how to fix it, because I don’t have the full code.

Whenever you reference a table from another script, roblox passes on the Memory Address of that script, meaning that when you modify something within the table, all the other scripts only see the last value modified.

A simple way to fix this is to use table.clone(yourTable)

If this doesn’t make sense, do ask for clarification.

For your system, when you call init, (because you’re not using OOP and creating new objects), you’re just setting self (which is the table) .MovePlayer to the newest player every time they join. You need to clone the table so that when you call Init, you don’t overwrite the older player every time.

Either that, or you use actual OOP (All about Object Oriented Programming)

Hi, just to clarify, table.clone should be used on the required module?
If so, I just tried doing that and I sadly got the same result.

	for _, Move in pairs(BasicMoves) do
		local Module = Move:Clone()
		Module.Parent = MoveFolder
		local ReqModule = table.clone(require(Module))
		ReqModule:Init(Player)
		RegisteredMoves[Move.Name] = ReqModule
		print(ReqModule.MovePlayer)
	end