When testing solo I did note encounter the issue that you had, however I did find this.
It appears that you force a random person to be the guard, remove them from the pool, then try to set a role for them. You wouldn’t really find this if you were testing with multiple people and one of the last people got picked as the Guard, but as I was testing solo it happened immediately.
I have a feeling that this is also similar to the issue you have.
I was Wrong-ish, I did more testing while typing this out and figured out more of the issue
An issue, which I presume is one of the issues, is that you select the player to change out of the pool of people.
For example, a 2 player array would be
You randomly pick 1 out of the 2 entry long array. That will now choose Player1 and get the position 1 from GetPlayers() array, which because the pool of players was made from GetPlayers(), lines up correctly. You then remove integer 1 from the available players, which is Player1. This is where the problem is made.
The new list after removing Player1 is
When you pick again, you are randomly picking from 1 - the length of the pool, which is also 1. You pick integer 1, which is Player2. When you get the Player object from GetPlayers(), you get the player at position 1. You end up picking Player1 again, as it was the first player in the GetPlayers() list. You then set it to the role again, however you remove Player2 from the available player pool as it is position 1 in that array.
To summarize, your “selected” player integer is not the same number in the GetPlayers() array. This and the beforementioned Guest no check means rewrites of multiple players and more issues.
The fix
Firstly, if you are going to pass a “gamestate” variable I would remove the OnGameEnd thing in it’s entirety so you do not need to link multiple functions to the same connect (this is just my preference, however you may keep it the same if it works for you).
Next, don’t make multiple arrays if your data is just going to be strung together all the time. You want what you need to specifically reference, not a list of what you might need to reference and then a specific number for it. What I would do is get the PlayerObject and make a list of what roles are NOT available, and then you can simplify your code.
This has been a long explanation which may not necessarily help as much as seeing the code itself, so below I provide beautiful and working code. Please let me know if you encounter more errors from this fix, and code on!
-- >> init vars
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local studio = game:GetService("RunService"):IsStudio()
-- >> our cool tables <<
local takenRoles = {}
local roles = {
"dog",
"cat",
"foo",
"oof"
}
-- >> FUNCTIONS HECK YEAHHHH <<
local function print2(stuff_to_print) -- for printing only in studio, you can delete this and control + f delete all the print2s if you want
if studio then
print(stuff_to_print)
end
end
local function onPlayerJoin(player)
print2("[ROLE] GOT PLAYER CONNECT AS")
print2(player)
local role = Instance.new("StringValue")
role.Name = "Role"
role.Parent = player
end
local function onGameStateChange(gameState) -- changed function name
if gameState == "Waiting for players" then -- I recommend doing something like "waiting" to shorten your vars but whatever floats your boat
table.clear(takenRoles) -- cleanup our taken roles
for i, v in ipairs(Players:GetPlayers()) do -- do ipairs so you get an integer pair back, pairs is meant for dictionaries
v.Role.Value = "None"
end
end
if gameState == "inter" then -- shortened for time purposes
local players_right_now = Players:GetPlayers()
print2(players_right_now)
for index, playerObject in ipairs(players_right_now) do -- do ipairs so you get an integer pair back, pairs is meant for dictionaries
print2("Began search")
local ChosenRole
repeat
local crINT = math.random(1,#roles) --chosenroleInteger to pick from our array
ChosenRole = roles[crINT]-- Make sure all the roles are strings
print2("Picked "..ChosenRole)
until table.find(takenRoles, ChosenRole) == nil --find if the provided string is found in the array takenRoles, will return nil if cannot be found
table.insert(takenRoles, ChosenRole)
print2("Set "..playerObject.Name.."'s role")
playerObject.Role.Value = ChosenRole
end
end
end
-- >> fancy connections <<
Players.PlayerAdded:Connect(onPlayerJoin)
ReplicatedStorage.GameState.Changed:Connect(onGameStateChange) -- bound to new function
print("Game role script has began - Made by evilmen8")