So this is the code I have for choosing gamemodes. Also, some unimportant parts of the code have been removed, but it shouldn’t affect how the script performs, unless I forgot to remove an “end” or something:
local GamemodeData = require(script.Parent.GamemodeData)
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- State tables
local currentRarities = {}
local cooldowns = {} -- [gamemodeName] = roundNumber when last picked
local roundsSincePicked = {} -- [gamemodeName] = rounds since last picked
local COOLDOWN_ROUNDS = 5
local RARITY_INCREMENT = 0.0001 -- percent per round (0.01%)
-- Initialize rarity and cooldown tables
local function initializeState()
for gamemodeName, data in GamemodeData.gamemodes do
currentRarities[gamemodeName] = data.rarity
cooldowns[gamemodeName] = -COOLDOWN_ROUNDS
roundsSincePicked[gamemodeName] = 0
end
end
initializeState()
local function getEligibleGamemodes(roundNumber)
local eligible = {}
for gamemodeName, data in GamemodeData.gamemodes do
local lastPickedRound = cooldowns[gamemodeName]
if roundNumber - lastPickedRound >= COOLDOWN_ROUNDS then
table.insert(eligible, gamemodeName)
end
end
return eligible
end
local function updateRarities(selectedGamemode)
for gamemodeName, data in GamemodeData.gamemodes do
if gamemodeName ~= selectedGamemode then
currentRarities[gamemodeName] = currentRarities[gamemodeName] + RARITY_INCREMENT
roundsSincePicked[gamemodeName] = roundsSincePicked[gamemodeName] + 1
else
currentRarities[gamemodeName] = data.rarity
roundsSincePicked[gamemodeName] = 0
end
end
end
end
local function weightedRandomChoice(gamemodeList)
local totalWeight = 0
for i, gamemodeName in gamemodeList do
totalWeight = totalWeight + currentRarities[gamemodeName]
end
local rand = math.random() * totalWeight
local cumulative = 0
for i, gamemodeName in gamemodeList do
cumulative = cumulative + currentRarities[gamemodeName]
if rand <= cumulative then
return gamemodeName
end
end
return gamemodeList[1]
end
local function selectGamemode(queuedGamemode, roundNumber)
local eligibleGamemodes = getEligibleGamemodes(roundNumber)
local chosenGamemode = nil
-- Calculate totalAdjustedRarity for eligible gamemodes
local totalAdjustedRarity = 0
for i, gamemodeName in eligibleGamemodes do
totalAdjustedRarity = totalAdjustedRarity + currentRarities[gamemodeName]
end
if queuedGamemode then
local lastPickedRound = cooldowns[queuedGamemode]
if roundNumber - lastPickedRound >= COOLDOWN_ROUNDS then
chosenGamemode = queuedGamemode
else
chosenGamemode = weightedRandomChoice(eligibleGamemodes)
end
else
if #eligibleGamemodes == 0 then
-- If all are on cooldown, ignore cooldowns for this round
local allGamemodes = {}
for gamemodeName, data in GamemodeData.gamemodes do
table.insert(allGamemodes, gamemodeName)
end
-- Calculate totalAdjustedRarity for all gamemodes
totalAdjustedRarity = 0
for i, gamemodeName in allGamemodes do
totalAdjustedRarity = totalAdjustedRarity + currentRarities[gamemodeName]
end
chosenGamemode = weightedRandomChoice(allGamemodes)
eligibleGamemodes = allGamemodes
else
chosenGamemode = weightedRandomChoice(eligibleGamemodes)
end
end
cooldowns[chosenGamemode] = roundNumber
updateRarities(chosenGamemode)
return chosenGamemode, currentRarities, totalAdjustedRarity, eligibleGamemodes
end
return {
selectGamemode = selectGamemode,
GetCurrentRarities = function() return currentRarities end,
GetCooldowns = function() return cooldowns end,
}
And this is the code I have that stores the rarities and other important values for each gamemode.
local gamemodes = {
["Gamemode1"] = {rarity = 0.14, queueableByOwner = true, queueableByPrivateServer = false, coinsReward = 1500},
["Gamemode2"] = {rarity = 2, queueableByOwner = true, queueableByPrivateServer = true, coinsReward = 250},
["Gamemode3"] = {rarity = 3, queueableByOwner = true, queueableByPrivateServer = true, coinsReward = 250},
}
-- Store the previous gamemode name
local previousGamemode = nil
local function setPreviousGamemode(name)
previousGamemode = name
end
local function getPreviousGamemode()
return previousGamemode
end
local function getTotalRarity()
local total = 0
for name, data in gamemodes do
if not data.limitedTimeOnly and not data.queueOnly then
total = total + data.rarity
end
end
return total
end
local function getGamemodePercent(name)
local data = gamemodes[name]
if not data then return 0 end
if data.limitedTimeOnly or data.queueOnly then return 0 end
local total = getTotalRarity()
if total == 0 then return 0 end
return math.floor((data.rarity / total) * 100 + 0.5)
end
local function canQueueGamemode(player, gamemodeName)
local data = gamemodes[gamemodeName]
if not data then return false end
if data.limitedTimeOnly or data.queueOnly then
if game.PrivateServerId ~= "" then
return data.queueableByPrivateServer
else
if player.UserId == game.CreatorId then
return data.queueableByOwner
end
end
return false
end
-- For normal gamemodes, use existing logic
if game.PrivateServerId ~= "" then
return data.queueableByPrivateServer
else
if player.UserId == game.CreatorId then
return data.queueableByOwner
end
end
return false
end
local function getGamemodeNames()
local names = {}
for name, _ in gamemodes do
table.insert(names, name)
end
return names
end
local function getCoinsReward(name)
local data = gamemodes[name]
if not data then return 0 end
return data.coinsReward or 0
end
local function isLimitedTimeOnly(name)
local data = gamemodes[name]
return data and data.limitedTimeOnly or false
end
local function isQueueOnly(name)
local data = gamemodes[name]
return data and data.queueOnly or false
end
local function getRandomGamemodeName()
-- Returns a random gamemode name that is NOT limited time only or queue only
local available = {}
for name, data in gamemodes do
if not data.limitedTimeOnly and not data.queueOnly then
table.insert(available, name)
end
end
if #available == 0 then return nil end
return available[math.random(1, #available)]
end
return {
gamemodes = gamemodes,
getTotalRarity = getTotalRarity,
getGamemodePercent = getGamemodePercent,
canQueueGamemode = canQueueGamemode,
getGamemodeNames = getGamemodeNames,
getCoinsReward = getCoinsReward,
isLimitedTimeOnly = isLimitedTimeOnly,
isQueueOnly = isQueueOnly,
getRandomGamemodeName = getRandomGamemodeName,
setPreviousGamemode = setPreviousGamemode,
getPreviousGamemode = getPreviousGamemode,
}
The problem is that even though the code is SUPPOSED to increase each gamemode’s chance by 0.01% to make them slowly get more common, what it ACTUALLY increases by is a lot more. For example, Gamemode1 would end up as 0.8% when it should be 0.15%. I’ve been trying to fix this for days but came back empty. It’d be greatly appreciated if somebody here has the answer