(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 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)
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.
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):
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.
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.