Choosing random player with player.GetAll() except for Traitors

If I want to choose a random player like this:

[lua]local randomply = player.GetAll()[math.random(1,#player.GetAll())][/lua]

How can I prevent that the chosen player is a traitor or dead ?


local function GetRandomInnocent()
	local players = player.GetAll() -- get players
	local rand = math.random(#players) -- get random value between 1 and number of players
	local player = players[rand] -- get player from players using rand

	-- if player is alive and they aren't a traitor then
	if (player:IsAlive() and player:GetRole() ~= ROLE_TRAITOR) then
		-- return the player
		return player
	end
	
	-- else try again
	return GetRandomInnocent()
end


Be careful with this; if all the players are dead or the only remaining players are traitors this will cause an infinite loop and the server/client will crash.

Make a list of all players you want to get a random value from first, and use that table instead of player.GetAll()

[editline]17th September 2017[/editline]

That’s a terrible solution, please don’t spread it, the idea/implementation is bad on so many levels.

This should work. Added spectator check for your convenience.



function randomPly()
	local plys={}
	for k,v in pairs(player.GetAll()) do
		if ~v:GetTraitor() and ~v:IsSpec() and v:IsAlive() then
			table.insert(plys,v)
		end
	end
	if #plys>0 then return plys[math.random(#plys)] end
	return false
end


Thanks for your help.

[editline]17th September 2017[/editline]

But Am I seeing this correctly that the chosen person is defined as “plys”?

local chosenPlayer = randomPly() is how you’d use that.

Thanks