Help with loadout system

Greetings, I am currently confused on how would I make this working.

I made this loadout system not too long ago but now everything is getting a bit confusing, thus I can’t solve my current problem.

1. My code might need some rehaul.

I think the current code, while works, it might need some fixes and improvements, so if you can help or aid me with the resources on how to make it more neat and readable, it would be very much appreciated!

2. The actual problem.

So there is a module script which contains all the information about the loadouts. Currently, everything seems to be working, except the loadout itself.
I’ll be providing the entire code to prevent any issues.

The loadout’s player count doesn’t properly update.

**Once again, I’m not asking for a fix, but rather information or details on how to achieve it.

Client-Side:

--// services

local tweenservice = game:GetService("TweenService")

local players = game:GetService("Players")

local replicatedstorage = game:GetService("ReplicatedStorage")

local lighting = game:GetService("Lighting")

local startergui = game:GetService("StarterGui")

local teams = game:GetService("Teams")


--// variables

local localplayer = players.LocalPlayer

local teamselection = script.Parent

local mainframe = teamselection:WaitForChild("MainFrame")

local loadoutframe = mainframe:WaitForChild("LoadoutFrame")

local scrollframe = loadoutframe:WaitForChild("ScrollFrame")

local invalidtext = mainframe:WaitForChild("InvalidText")

local teamframe = mainframe:WaitForChild("TeamFrame")

local changeteam = teamselection:WaitForChild("ChangeTeam")

local team_a_button = teamframe:WaitForChild("TeamA")

local team_b_button = teamframe:WaitForChild("TeamB")

local teamselect = replicatedstorage:WaitForChild("TeamSelect")


--// sfx

local click = script:WaitForChild("Click") -- Sound played when clicked.
local invalid = script:WaitForChild("Invalid") -- Sound played when invalid.


--// settings


local have_startblur = true -- Have a blur on screen at the start of the menu.

local info = TweenInfo.new(1, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut) -- Default tween info.

local loadoutmodule = require(game:GetService("ReplicatedStorage").LoadoutModule)


--// IMPORTANT //


local team_a = teams:WaitForChild("Red") -- Set the "A" team

local team_b = teams:WaitForChild("Blue") -- Set the "B" team

--// startup

local startblur = nil;

local selected_team = nil;

if have_startblur == true then
	
	startblur = Instance.new("BlurEffect")
	startblur.Name = "StartBlur"
	startblur.Size = 32
	startblur.Parent = lighting
	
end



startergui:SetCoreGuiEnabled(Enum.CoreGuiType.All, false)


--// functions





function onChangeButton()
	
	script.Click:Play()
	mainframe.Visible = not mainframe.Visible
	teamframe.Visible = true
	loadoutframe.Visible = false
	
	for _, gui in pairs(scrollframe:GetDescendants()) do
		print(gui.Name)
		if gui:IsA("GuiObject") then
			if gui:IsA("Frame") then
				gui:Destroy()
			end
		end
	end
	
end


function onJoinLoadout(loadout, selectedteam)
	
	replicatedstorage:WaitForChild("LoadoutSelect"):FireServer(loadout, selectedteam)
	loadoutframe.Visible = false
	mainframe.Visible = false
	
	for _, gui in pairs(scrollframe:GetDescendants()) do
		if gui:IsA("GuiObject") then
			if gui:IsA("Frame") then
				gui:Destroy()
			end
		end
	end
	
end



function changeTeam(selectedteam)
	
	if selectedteam == team_a then
		
		-- Team-A selected
		
		if localplayer.Team == selectedteam then return end
		
		teamselect:FireServer(selectedteam)
		
		selected_team = selectedteam
		
		for _, ui in pairs(scrollframe:GetChildren()) do
			
			if ui:IsA("GuiObject") then
				
				if ui.Name == "Loadout" then
					
					ui:Destroy()
					
				end
				
			end
			
		end
		
		for index, loadout in pairs(loadoutmodule[selectedteam.Name]) do

			local template = replicatedstorage.Loadout:Clone()
			template.Name = loadout.LName
			template.Parent = scrollframe

			template:WaitForChild("ClassLabel").Text = tostring(index)

			template:WaitForChild("PlayerCount").Text = tostring(loadout.CurrentPlr).."/"..tostring(loadout.PlrCount)

			template:WaitForChild("JoinButton").MouseButton1Click:Connect(function()
				onJoinLoadout(loadout, selectedteam)
			end)

		end
		
	elseif selectedteam == team_b then
		
		-- Team-B selected
		
		if localplayer.Team == selectedteam then return end
		
		teamselect:FireServer(selectedteam)
		selected_team = selectedteam
		

		for _, ui in pairs(scrollframe:GetChildren()) do
			
			if ui:IsA("GuiObject") then
				
				if ui.Name == "Loadout" then
					
					ui:Destroy()
					
				end
				
			end
		end
		
		for index, loadout in pairs(loadoutmodule[selectedteam.Name]) do
			
			local template = replicatedstorage.Loadout:Clone()
			template.Name = loadout.LName
			template.Parent = scrollframe
			
			template:WaitForChild("ClassLabel").Text = tostring(index)

			template:WaitForChild("PlayerCount").Text = tostring(loadout.CurrentPlr).."/"..tostring(loadout.PlrCount)
			
			template:WaitForChild("JoinButton").MouseButton1Click:Connect(function()
				onJoinLoadout(loadout, selectedteam)
			end)
			
		end
		
	end
	
end






function onTeamSelect(status)
	
	if status == "invalid" then
		
		-- possible team im-balance!
		
		-- show the invalid message
		
		invalidtext.TextTransparency = 0
		invalidtext.Visible = true
		
		invalid:Play()
		
		-- tween out
		
		spawn(function()
			
			task.wait(1)
			
			local invalidtween = tweenservice:Create(invalidtext, info, {TextTransparency = 1})
			invalidtween:Play()
			
		end)
		
	elseif status == "success" then
		
		-- team-selection success!
		
		click:Play()
		
		teamframe.Visible = false
		loadoutframe.Visible = true
		startergui:SetCoreGuiEnabled(Enum.CoreGuiType.All, true)
		
		
		if have_startblur == true and startblur ~= nil then
			
			local blurtween = tweenservice:Create(startblur, info, {Size = 0})
			blurtween:Play()
			blurtween.Completed:Wait()
			startblur:Destroy()
			
		end
		
	end
end

function onUpdateLoadout(loadout)
	
	for index, ui in pairs(scrollframe:GetChildren()) do
		if ui:IsA("GuiObject") then
			if ui.Name == loadout.LName then
				-- same thing
				
				ui.PlayerCount.Text = tostring(loadout.CurrentPlr).."/"..tostring(loadout.PlrCount)
			end
		end
		
	end
	
end










-- // connections \\ --

replicatedstorage:WaitForChild("UpdateLoadout").OnClientEvent:Connect(function(loadout) onUpdateLoadout(loadout) end)

teamselect.OnClientEvent:Connect(function(status) onTeamSelect(status) end)

changeteam.MouseButton1Click:Connect(function() onChangeButton() end)

team_a_button.MouseButton1Click:Connect(function() changeTeam(team_a) end)

team_b_button.MouseButton1Click:Connect(function() changeTeam(team_b) end)

Server-Side:

--// services

local tweenservice = game:GetService("TweenService")

local players = game:GetService("Players")

local replicatedstorage = game:GetService("ReplicatedStorage")

local lighting = game:GetService("Lighting")

local startergui = game:GetService("StarterGui")

local teams = game:GetService("Teams")


--// variables


local teamselect = replicatedstorage.TeamSelect


--// IMPORTANT //


local team_a = teams.Red

local team_b = teams.Blue


--// settings


local loadoutmodule = require(replicatedstorage.LoadoutModule)


--// functions


players.PlayerAdded:Connect(function(player)
	
	player:SetAttribute("Loadout", "None")
	
end)

teamselect.OnServerEvent:Connect(function(player, selectedteam)
	
	if player.Team == selectedteam then return end
	
	local char = player.Character
	
	local a_plrs = #team_a:GetPlayers()
	
	local b_plrs = #team_b:GetPlayers()
	
	if a_plrs<b_plrs then
		
		-- B team has more plr (imbalance)
		
		if selectedteam == team_a then
			
			player.Team = selectedteam
			teamselect:FireClient(player, "success")
			
		else
			teamselect:FireClient(player, "invalid")
		end
		
	elseif b_plrs<a_plrs then
		
		-- A team has more plr (imbalance)
		
		if selectedteam == team_b then
			
			player.Team = selectedteam
			teamselect:FireClient(player, "success")
			
		else
			
			teamselect:FireClient(player, "invalid")
			
		end
	elseif a_plrs == b_plrs then
		
		-- equal plrs (balance)
		
		player.Team = selectedteam
		teamselect:FireClient(player, "success")
		
	else
		
		teamselect:FireClient(player, "invalid")
		
	end
	
end)

replicatedstorage.LoadoutSelect.OnServerEvent:Connect(function(player, loadout, team)
	
	local char = player.Character
	
	local player_loadout = player:GetAttribute("Loadout")
	
	if player_loadout == "None" then
		player:SetAttribute(loadout)
	else
		team[player_loadout].CurrentPlr -= 1
		player:SetAttribute(loadout)
	end
	
	loadout.CurrentPlr += 1

	replicatedstorage.UpdateLoadout:FireClient(player, loadout)
	
end)

Module-Script:

local players = game:GetService("Players")

local serverstorage = game:GetService("ServerStorage")

local classes = {
	
	--// LOADOUT FOR A TEAM
	
	["Red"] = {
		
		
		
		
		["Rifleman"] = {
			
			["LName"] = "Rifleman"; -- name of loadout
			
			["PlrCount"] = 18; -- max player limit
			
			["CurrentPlr"] = 0; -- current player count
			
		};
		
		
		

		["Recon"] = {
			
			["LName"] = "Recon";
			
			["PlrCount"] = 9;
			
			["CurrentPlr"] = 0;
			
		}
	};
	
	--// LOADOUT FOR B TEAM
	
	["Blue"] = {
		
		
		
		
		["Assault"] = {
			
			["LName"] = "Assault";
			
			["PlrCount"] = 18;
			
			["CurrentPlr"] = 0;
			
		};
		
		
		
		
		
		["Sniper"] = {
			
			["LName"] = "Sniper";
			
			["PlrCount"] = 9;
			
			["CurrentPlr"] = 0;
			
		}
	}
	
}

function classes.createLoadoutFolder(loadout, team)
	
	local loadoutfolder = Instance.new("Folder")
	loadoutfolder.Name = loadout.Name
	loadoutfolder.Parent = serverstorage.Tools[team.Name]
	
	return loadoutfolder
	
end


return classes

The error lies primarily in the client and server scripts, the issue is that, the loadout’s CurrentPlr value is not working properly. Now I could use Values, but it would take a lot of time to switch and ultimately, I’d say modulescripts would be better performance wise aswell. If you would need anymore details, I would be glad to provide them.