Building a chance increase system

I’ve looked everywhere for this and haven’t found a workable, working solution for this.

The issue is that I’m trying to make a chance to be a “Ghost” system, initially all players should have a 5% chance to be the ghost, but since everyone has the same chance, a random player will be choosing and then their chance of being the ghost would still be 5%, while that of the other players not chosen would increase by another 5%, but I couldn’t get it to work so that the next one with the highest chance would be chosen, and so on.

An observation is that I already checked a post similar to this one about a system of chance to MM2, but it didn’t work correctly.

I have a script that creates an IntValue inside the Player which stores the chances, called “GhostChance”.

Any help will be appreciated.

1 Like

Just do a weighed random. Add 1 to everyones weight at the start of every round. Set the weight back to 0 for the person that was just chosen

local tickets= {}
game.Players.PlayerAdded:Connect(function(plr)
    tickets[plr] = 1 --Give every player who joins a ticket
end)

game.Players.PlayerRemoving:Connect(function(plr)
    tickets[plr] = nil --Remove a player from the ticket pool when they leave
end)

local function pickGhost()
    local total = 0 --Count up how many tickets there are total so you know what range to pick from
    for _, i in pairs(tickets) do
        total += i
    end
    
    local num = math.random(1,total) --pick a random number
    local chosen
    for plr, i in pairs(tickets) do
        num-=i
        if num <=0 then
            chosen = plr --this players ticket was chosen
            break
        end
    end

    tickets[chosen] = 0 --Reset the chosen ones ticket count.  A ticket count of 0 or less will break the system, but the player will be given a ticket immediately after this

    for plr, _ in pairs(tickets) do
        tickets[plr] +=1 --Give everyone an extra ticket
    end

    return chosen --Return the ghost player object
end

This code could probably be written better, but it’s the general idea. That way as the game progresses, the longer a player goes without being the ghost, their chances just get higher until they finally are.

ok, but i need to transfer the % to the intvalue stored inside the player to the gui see them.
besides I have a question, since I have an intValue inside each player, maybe it’s not necessary to use a table of “tickets” and use a table of players and check the intvalue of that?

You can use the intvalue instead, but essentially it’s the same thing as a table. Personally I like working with tables more, but you can modify it however you wish. I did go and build a better version of the system though. It has a function you can use to get each players percentage. You can set your intvalue where I put the comment.

I haven’t tested it, but it should work

local tickets = {}
local ticketsTotal = 0

local function givePlayerTickets(plr, count)
	count = count or 1
	tickets[plr] += count --Give everyone an extra ticket
	ticketsTotal += count
end

local function removePlayerTickets(plr, count)
	count = count or tickets[plr]
	ticketsTotal -= count
	tickets[plr] -= count
end

local function getPlayerChance(plr)
	return tickets[plr]/ticketsTotal
end

local function pickGhost()
	local num = math.random(1, ticketsTotal)
	for chosen, i in pairs(tickets) do
		num-=i
		if num <=0 then
			removePlayerTickets(chosen)
			for plr,_ in pairs(tickets) do
				givePlayerTickets(plr)
				--I put the code for updating the intValues in givePlayerTickets and removePlayerTickets so it will always be up to date.  There is also a waitForChild in the playerAdded function to make sure it doesn't error.  If I named something wrong those 3 locations are what you'll have to change
			end
			return chosen
		end
	end
end

game.Players.PlayerAdded:Connect(function(plr)
	tickets[plr] = 0
	givePlayerTickets(plr)
end)
game.Players.PlayerRemoving:Connect(function(plr)
	removePlayerTickets(plr)
	tickets[plr] = nil
end)

Great!, I will adapt it in my code and test it, if eveything works fine I will mark as solution, Thanks!

Ok, I tested and it is giving error in addition and subtraction in the function that gives and removes tickets.

Ahh. I made a mistake in the playeradded section. I tried to add nil and a number

Here is the (hopefully) final version.

local tickets = {}
local ticketsTotal = 0

local function givePlayerTickets(plr, count)
	count = count or 1
	tickets[plr] += count --Give everyone an extra ticket
	ticketsTotal += count
	plr.GhostChance.Value = math.floor(tickets[plr]/ticketsTotal*100)
end

local function removePlayerTickets(plr, count)
	count = count or tickets[plr]
	ticketsTotal -= count
	tickets[plr] -= count
	plr.GhostChance.Value = math.floor(tickets[plr]/ticketsTotal*100)
end

local function getPlayerChance(plr)
	return tickets[plr]/ticketsTotal
end

local function pickGhost()
	local num = math.random(1, ticketsTotal)
	for chosen, i in pairs(tickets) do
		num-=i
		if num <=0 then
			removePlayerTickets(chosen)
			for plr,_ in pairs(tickets) do
				givePlayerTickets(plr)
				--I put the code for updating the intValues in givePlayerTickets and removePlayerTickets so it will always be up to date.  There is also a waitForChild in the playerAdded function to make sure it doesn't error.  If I named something wrong those 3 locations are what you'll have to change
			end
			return chosen
		end
	end
end

game.Players.PlayerAdded:Connect(function(plr)
	tickets[plr] = 0
	plr:WaitForChild("GhostChance") --make sure it loads before trying to access it
	givePlayerTickets(plr)
end)
game.Players.PlayerRemoving:Connect(function(plr)
	removePlayerTickets(plr)
	tickets[plr] = nil
end)

well, now it’s selecting all players to be the ghost somehow

I will try your old method to see if it works.

none of them are working, they both is selecting more than one player

Nevermind, now is working fine, it was just a mistake of mine.

1 Like