Automatic Roblox Luau Team Balancing
Generate a robust automatic balancing system for Roblox matches, designed to run authoritatively on the server. The script distributes players between teams, monitors joins and leaves, avoids excessive swapping, and can account for capacity limits, spectator/lobby teams, and skill differences when data is available.
The prompt requests the real context of your project — Explorer structure, Team object names, Attributes, RemoteEvents, and specific rules — before producing a ready-to-paste Luau code file. It is intended for developers who need a scalable and secure solution for competitive, cooperative, or round-based games.
Act as a senior Roblox developer, specializing in scalable Luau, multiplayer architecture, and server-authoritative security. Create a complete automatic team balancing system for Roblox, adapted rigorously to the context of my game provided below. The main result must be ONE complete Luau Script, ready to paste into Roblox Studio. The required type is `Script` (not LocalScript and not ModuleScript), and it must be placed in `ServerScriptService`. The system must use the `Teams` service and assign `Player.Team` and, when appropriate, `Player.Neutral` exclusively on the server. Do not use the client as the source of truth to define teams, player balance, score, damage, currency, inventory, or swap eligibility. Before writing the code, read and consider this context for my project. If any item is missing, create safe default values, group them in a CONFIG section at the top of the script, and explain in a comment how to change them: [PASTE HERE THE CONTEXT OF MY GAME] - Existing teams in the Teams service: (e.g., Red, Blue, Spectators, Lobby) - Exact names of the teams that participate in the match: - Teams that should be ignored in balancing: - Does the game use rounds? Describe existing states, Attributes, or Values (e.g., ReplicatedStorage.GameState): - Relevant Explorer structure and object paths: - Existing RemoteEvents/RemoteFunctions and their purposes: - Is there a party/group system? Where is the information stored (Attribute, Value, DataStore cache, etc.)? - Is there score, MMR, level, or skill? Provide the path and value type: - Maximum allowed difference between teams: - Maximum capacity per team, if any: - Can players choose a team manually? How does that happen? - Special rules for respawn, lobby, spectators, admins, or game modes: - Roblox version/features I should not use: [END OF CONTEXT] Mandatory functional requirements: 1. When joining, each player must be assigned to the least populated eligible team. On ties, use a fair and predictable rule, such as rotation, a persistent in-memory counter, or a server-controlled random choice. 2. Rebalance when players join or leave, and also provide a well-named public/local function for the server to call at the start/end of a round or after state changes. 3. Never move players from ignored, lobby, or spectator teams unless the configuration explicitly allows it. 4. Only perform a swap if it truly reduces the imbalance and respects maximum capacity, round protections, and eligibility criteria. 5. Implement per-player cooldown and a global rebalance interval to prevent repeated swapping, flickering, and exploitation of rapid events. 6. If valid MMR/skill data exists in the context, prioritize a distribution that reduces the total skill difference without violating player count difference. If not, use player count only. 7. If there is a party, do not separate members of the same party when possible; if it is mathematically impossible, prioritize stability and document the decision in the code. 8. Preserve players whose Character has not loaded and do not depend on Humanoid, SpawnLocation, or GUI for the core logic. Team assignment must work independently of respawn. 9. Handle missing teams, invalid values, players removed during operation, zero eligible teams, and configuration errors safely. Use `warn()` with helpful messages, without unnecessarily interrupting the server. 10. Do not create new RemoteEvents unless necessary. If the context includes RemoteEvents for manual team change requests, the server must fully validate the player, round state, allowed target, capacity, cooldown, and all eligibility before changing any team. Never trust arguments sent by the client. Structure the code with a clearly typed CONFIG where it makes sense, small and readable functions, professional comments in Portuguese, organized event connections, and cleanup of connections/state when applicable. Avoid infinite loops with `while true do` for polling; prefer `Players.PlayerAdded`, `Players.PlayerRemoving`, relevant state changes, and controlled scheduling with `task.delay`. Do not use outdated APIs. Do not depend on plugins or external modules. Deliver the response in this order: (1) a brief list of assumptions adopted from the context; (2) the exact Explorer path and the script type; (3) the full code in a single Markdown ` ```lua ` block, with no pseudocode, no omitted snippets, and with comments; (4) objective instructions for testing in Play mode with multiple clients in Roblox Studio, including cases for join, leave, tie, capacity, lobby/spectator, cooldown, and party/MMR if configured; (5) a short list of CONFIG parameters I should adjust. Do not deliver client code unless I have explicitly provided a manual RemoteEvent that requires integration, and you explain that validation still remains on the server.