Module script is running when not called

(Sorry for the very vague title I wasn’t quite sure how to explain what was going on)

I currently have a module script that updates the players’ team and attributes like health and some items in their backpack. Initially, everything is fine but when I try to flip flop between teams I’m experiencing issues, here are some gifs that better show what the issue is:

case 1: https://gyazo.com/a617477844e5263e067377b6744dcb60
case 2: https://gyazo.com/a617477844e5263e067377b6744dcb60

Case 1 is when I first become a civilian which ends up overwriting ghoul code, and case 2 is the opposite.

Here is my main function body from the module script:

function team.update_inv(player, team)
	player.CharacterAdded:Connect(function(char)
		local backpack = player:FindFirstChild("Backpack")
		
		if team == "ghoul" then
			if not backpack:FindFirstChild("Eat") then
				print("ran ghoul")
				local eat = f_tools:WaitForChild("Eat"):Clone()
				eat.Parent = backpack
			end
		end
		if team == "civilian" then
			print("ran civ")
			if backpack:FindFirstChild("Eat") then
				backpack:FindFirstChild("Eat"):Destroy()
			end
		end
	end)
end

function team.set_ghoul(char)
	char:SetAttribute("Team", "Ghoul")
	char:SetAttribute("MaxHealth", 200)
	
	local player = Players:GetPlayerFromCharacter(char)
	
	player.Team = Teams:FindFirstChild("Ghoul")
	player:LoadCharacter()
end

function team.set_civilian(char)
	char:SetAttribute("Team", "Civilian")
	char:SetAttribute("MaxHealth", 100)
	
	local player = Players:GetPlayerFromCharacter(char)

	player.Team = Teams:FindFirstChild("Civilian")
	player:LoadCharacter()
end

And here is the serverscript thats running the module:

re_team.OnServerEvent:Connect(function(player, action)
	local char = player.Character or player.CharacterAdded:Wait()
	
	if action == "ghoul" then
		module_team.update_inv(player, "ghoul")
		module_team.set_ghoul(char)
	end
	if action == "civilian" then
		module_team.update_inv(player, "civilian")
		module_team.set_civilian(char)
	end
end)

Why don’t you post in #help-and-feedback when you need help? What does this have to do with #development-discussion.

Oh sorry, I thought this was where you posted for help. Thanks for letting me know I’ll move this post over.

Bumping because its been close to a day.

The team.update_inv creates a connection that will run whenever the player’s character is created, but these connections are not disconnected at any point, so they accumulate every time you switch teams and team.update_inv is called, the connections stack up and all run on every spawn.

You can resolve this by disconnecting the prior connection before making a new one, or only making one connection when the player first joins the game and getting the team value from some other source than the argument passed in to team.update_inv.

1 Like

Sorry for the late reply but thank you for this!

1 Like

I would remove the constant change between char and player. Surely this is more readable and scalable (i.e. any added type will require changes to the module -core code-and not the event system):

re_team.OnServerEvent:Connect(function(player, action)
	module_team.update(player, action)
end)

local health_table = { Civilian = 100, Ghoul = 200 }

function team.set_char(player,team)
	player:SetAttribute("Team", team)
	player:SetAttribute("MaxHealth",health_table[team])
	player.Team = Players:WaitForChild(team,3)
	player:LoadCharacter()
end

function team.update(player, team)

	local backpack = player:WaitForChild("Backpack",3)
	if not backpack then
		-- critical failure
		return
	end

	local tool = backpack:WaitForChild(team,3)
	if tool then
		-- destroy the old first
		tool:Destroy()
	end

	local team_tool = f_tools:WaitForChild(team,3)
	local team_tool_clone = team_tool and team_tool:Clone()
	if team_tool_clone then
		-- tool exists and is cloned successfully so re-parent it
		team_tool_clone.Parent = backpack
	end
	
	-- now set character in one function without unscalable branched logic
	team.set_char(player,team)

end

This is in no way definitive or tested, but the overall idea is presented and the method to reduce complexity and increase scalability. Also, I’m not sure this system needs a ModuleScript to achieve this. A ModuleScriptcontains transferrable code that can be used by any part of a program, i.e. defining shapes, colours, trigonometry functions, search algorithms, text manipulators , etc. that can be used by any function. This ModuleScript functions as a singleton and cannot be used by other parts of the program.

1 Like

First and foremost thank you so much for the help I really appreciate it,

I’d like to mention I 100% agree that there is no real need for Module Scripts but I’m still relatively new to Roblox Studio and just trying to get used to using them.

So I’ve sorta already got a fix it’s just very cave-man like I feel. It’s pretty straightforward.

(Module Script)

function update_inv(player, team)
	local starter_gear = player:WaitForChild("StarterGear")

	if team == "apostle" then
		print("ran apostle")
		if not starter_gear:FindFirstChild("Eat") then
			local eat = f_tools:WaitForChild("Eat"):Clone()
			eat.Parent = starter_gear
		end
	end
	if team == "human" then
		print("ran human")
		if starter_gear:FindFirstChild("Eat") then
			starter_gear:FindFirstChild("Eat"):Destroy()
		end
	end
end

function team.set_apostle(char)
	char:SetAttribute("Team", "Apostle")
	char:SetAttribute("MaxHealth", 200)
	
	local player = Players:GetPlayerFromCharacter(char)
	
	update_inv(player, "apostle")
	
	player.Team = Teams:FindFirstChild("Apostle")
	player:LoadCharacter()
end

function team.set_human(char)
	char:SetAttribute("Team", "Human")
	char:SetAttribute("MaxHealth", 100)
	
	local player = Players:GetPlayerFromCharacter(char)

	update_inv(player, "human")

	player.Team = Teams:FindFirstChild("Human")
	player:LoadCharacter()
end

I really like what you’ve done in terms of scalability and will definitely incorporate that into here and future code that I write.

Thanks again!