Hello. I have some code here whose function is to wait 15 seconds for the intermission, then wait 10 seconds for map voting. At the start of these 10 seconds, 3 maps are randomly chosen to be displayed on the display pads. Players will vote on which map they want by stepping on the part that correlates with the map of their choice (kind of like in Murder Mystery 2). After map voting, the maps on the display pads and their votes disappear and the game goes on by telling everyone which map was the winner. Then it plays the round for 10 seconds and it loops, etc.
Everything works up until picking a winner. It seems as if the first time around, it works perfectly, but it seems to become inconsistent in the next rounds as it randomly picks a map on the display pads to win, rather than picking the map with the most votes. If you can find an error with my code, please let me know.
Thank you.
local rep = game:GetService("ReplicatedStorage") local players = game:GetService("Players") local minutesvalue = rep:WaitForChild("Minutes") local secondsvalue = rep:WaitForChild("Seconds") local minutes = 0 --minutes local seconds = 11 --seconds local status = game.Players.LocalPlayer.PlayerGui.Status:WaitForChild("Status") local VotingSystem = game.Workspace:WaitForChild("VotingSystem") local Pad1 = VotingSystem:WaitForChild("Pad1") local Pad2 = VotingSystem:WaitForChild("Pad2") local Pad3 = VotingSystem:WaitForChild("Pad3") local title1 = VotingSystem.VotingDisplay.SurfaceGui.Pad1:WaitForChild("Header") local title2 = VotingSystem.VotingDisplay.SurfaceGui.Pad2:WaitForChild("Header") local title3 = VotingSystem.VotingDisplay.SurfaceGui.Pad3:WaitForChild("Header") local ReplicatedStorage = game:GetService("ReplicatedStorage") local doneVoting = ReplicatedStorage:WaitForChild("doneVoting") title1.Text = "" title2.Text = "" title3.Text = "" while true do status.Text = "Intermission" secondsvalue.Value = 15 repeat secondsvalue.Value = secondsvalue.Value - 1 wait(1) until secondsvalue.Value <= 0 and minutesvalue.Value <= 0 status.Text = "Voting In Progress" secondsvalue.Value = 10 game.Players.PlayerAdded:Connect(function(player) local Vote = Instance.new("StringValue") Vote.Name = "Vote" Vote.Parent = player Vote.Value = "NA" end) -- Vote Counter local function UpdateDisplay() VotingSystem.VotingDisplay.SurfaceGui.Pad1.Counter.Text = Pad1.Votes.Value VotingSystem.VotingDisplay.SurfaceGui.Pad2.Counter.Text = Pad2.Votes.Value VotingSystem.VotingDisplay.SurfaceGui.Pad3.Counter.Text = Pad3.Votes.Value end for i, Pad in pairs (game.Workspace.VotingSystem:GetChildren())do if Pad.Name ~= "VotingDisplay" then Pad.Touched:Connect(function(hit) if hit.Parent:FindFirstChild("Humanoid")then local char = hit.Parent local player = game.Players:GetPlayerFromCharacter(char) if player.Vote.Value ~= Pad then Pad.Votes.Value = Pad.Votes.Value + 1 if player.Vote.Value ~= "NA" then local padToSubtract = VotingSystem:FindFirstChild(player.Vote.Value) padToSubtract.Votes.Value = padToSubtract.Votes.Value - 1 end player.Vote.Value = Pad.Name UpdateDisplay() end end end) end end -- Picking which maps to vote between local Maps = game.Lighting.Maps:GetChildren() local voteMap1 = Maps[math.random(1, #Maps)] local voteMap2 = Maps[math.random(1, #Maps)] local voteMap3 = Maps[math.random(1, #Maps)] if voteMap2 == voteMap1 then repeat voteMap2 = Maps[math.random(1, #Maps)] until voteMap2 ~= voteMap1 end if voteMap3 == voteMap2 or voteMap3 == voteMap1 then repeat voteMap3 = Maps[math.random(1, #Maps)] until voteMap3 ~= voteMap2 and voteMap3 ~= voteMap1 end title1.Text = tostring(voteMap1) title2.Text = tostring(voteMap2) title3.Text = tostring(voteMap3) -- The calculating winner function local function CalculateWinner() local padVotes = { [tostring(voteMap1)] = Pad1.Votes.Value, [tostring(voteMap2)] = Pad2.Votes.Value, [tostring(voteMap3)] = Pad3.Votes.Value, } local highest = 0 local pad = nil for i, v in pairs (padVotes) do if v > highest then highest = v pad = i end end return pad end -- Waiting for voting timer to run out repeat secondsvalue.Value = secondsvalue.Value - 1 wait(1) until secondsvalue.Value <= 0 and minutesvalue.Value <= 0 -- (Calculating winner before votes reset.) CalculateWinner() -- Resetting data spawn(function() while wait(1) do if secondsvalue.Value <= 0 then doneVoting.Value = true CalculateWinner() Pad1.Votes.Value = 0 Pad2.Votes.Value = 0 Pad3.Votes.Value = 0 VotingSystem.VotingDisplay.SurfaceGui.Pad1.Counter.Text = 0 VotingSystem.VotingDisplay.SurfaceGui.Pad2.Counter.Text = 0 VotingSystem.VotingDisplay.SurfaceGui.Pad3.Counter.Text = 0 title1.Text = "" title2.Text = "" title3.Text = "" wait(5) doneVoting.Value = false end end end) -- Stating the winning map local mapWinner = CalculateWinner() if mapWinner == nil then local padVotes = {tostring(voteMap1),tostring(voteMap2),tostring(voteMap3)} mapWinner = padVotes[math.random(1,#padVotes)] end status.Text = "Loading Map ".. mapWinner wait(5) status.Text = "Round In Progress" minutesvalue.Value = minutes secondsvalue.Value = seconds repeat if secondsvalue.Value <= 0 then minutesvalue.Value = minutesvalue.Value - 1 secondsvalue.Value = 59 else secondsvalue.Value = secondsvalue.Value - 1 end wait(1) until secondsvalue.Value <= 0 and minutesvalue.Value <= 0 status.Text = "Game Over!" wait(5) end
Improvements
Use :GetService()
for the Workspace
and Players
Use :WaitForChild()
to make sure an instance exists before using it
Place newly created functions outside of your loop, this makes the code more efficient as it doesn't have to create an entirely new function each time the loop is complete and is more easily read.
For code that is repeated, you can make another local function (such as with your repeats) instead
Multiple times in your code, you call CalculateWinner() but do nothing with it, thus these calls are unnecessary
You are calling tostring() on what I presume to be a model, instead just use the Name
property.
When using :FindFirstChild()
make sure to check the result is not nil
Issues
spawn
executes the given function in a new thread, so once the while
loop in the spawned function begins, you never end it and you create multiple of these after each loop. The loop will continue during the round and end of intermission as well because of the condition. Resetting it once is enough.
Under the Touched event, you have the Line 59 "if player.Vote.Value ~= Pad then", however, the Value of "Vote" is a string, while "Pad" is an object, so this condition will always return true.
Assuming this is a ServerScript, you cannot call "game.Players.LocalPlayer", if it is a LocalScript, then the values set will not coincide for all players on the server and the below code should be placed in a ServerScript in ServerScriptService instead
Revised Server Script
-- Local Variables local players = game:GetService("Players") local rep = game:GetService("ReplicatedStorage") local doneVoting = rep:WaitForChild("doneVoting") local minutesvalue = rep:WaitForChild("Minutes") local secondsvalue = rep:WaitForChild("Seconds") local VotingSystem = game:GetService("Workspace"):WaitForChild("VotingSystem") local Pad1 = VotingSystem:WaitForChild("Pad1") local Pad2 = VotingSystem:WaitForChild("Pad2") local Pad3 = VotingSystem:WaitForChild("Pad3") local PV1 = Pad1:WaitForChild("Votes") local PV2 = Pad1:WaitForChild("Votes") local PV3 = Pad1:WaitForChild("Votes") local VGui = VotingSystem:WaitForChild("VotingDisplay"):WaitForChild("SurfaceGui") local PC1 = VGui:WaitForChild("Pad1"):WaitForChild("Counter") local PC2 = VGui:WaitForChild("Pad2"):WaitForChild("Counter") local PC3 = VGui:WaitForChild("Pad3"):WaitForChild("Counter") local title1 = VGui:WaitForChild("Pad1"):WaitForChild("Header") local title2 = VGui:WaitForChild("Pad2"):WaitForChild("Header") local title3 = VGui:WaitForChild("Pad3"):WaitForChild("Header") title1.Text = "" title2.Text = "" title3.Text = "" local voteMap1 = nil local voteMap2 = nil local voteMap3 = nil local minutes = 0 local seconds = 11 -- Update Status for all Players local function UpdateStatus(text) for _, player in pairs(players:GetPlayers()) do local status = player:WaitForChild("PlayerGui"):WaitForChild("Status"):WaitForChild("Status") status.Text = text end end -- Vote Counter local function UpdateDisplay() PC1.Text = PV1.Value PC2.Text = PV2.Value PC3.Text = PV3.Value end -- Picks Maps to Vote For local function RandomizeMaps() local Maps = game:GetService("Lighting"):WaitForChild("Maps"):GetChildren() voteMap1 = Maps[math.random(1, #Maps)] voteMap2 = Maps[math.random(1, #Maps)] voteMap3 = Maps[math.random(1, #Maps)] if voteMap2 == voteMap1 then repeat voteMap2 = Maps[math.random(1, #Maps)] until voteMap2 ~= voteMap1 end if voteMap3 == voteMap2 or voteMap3 == voteMap1 then repeat voteMap3 = Maps[math.random(1, #Maps)] until voteMap3 ~= voteMap2 and voteMap3 ~= voteMap1 end title1.Text = voteMap1.Name title2.Text = voteMap2.Name title3.Text = voteMap3.Name end -- Determine Winning Map local function CalculateWinner() local padVotes = { [voteMap1.Name] = PV1.Value, [voteMap2.Name] = PV2.Value, [voteMap3.Name] = PV3.Value, } local highest = 0 local pad = nil for map, vote in pairs(padVotes) do if vote > highest then highest = vote pad = map end end if pad == nil then local padTbl = {voteMap1.Name, voteMap2.Name, voteMap3.Name} pad = padTbl[math.random(1, #padTbl)] end return pad end -- Reset Pads local function ResetVotes() wait(1) doneVoting.Value = true PV1.Value = 0 PV2.Value = 0 PV3.Value = 0 PC1.Text = 0 PC2.Text = 0 PC3.Text = 0 title1.Text = "" title2.Text = "" title3.Text = "" voteMap1 = nil voteMap2 = nil voteMap3 = nil for _, player in pairs(players:GetPlayers()) do local plyrVote = player:WaitForChild("Vote") plyrVote.Value = "NA" end wait(5) doneVoting.Value = false end local function WaitTime(min, sec) minutesvalue.Value = min secondsvalue.Value = sec repeat if secondsvalue.Value <= 0 then minutesvalue.Value = minutesvalue.Value - 1 secondsvalue.Value = 59 else secondsvalue.Value = secondsvalue.Value - 1 end wait(1) until secondsvalue.Value <= 0 and minutesvalue.Value <= 0 end -- Give Players Voting Tags players.PlayerAdded:Connect(function(player) local Vote = Instance.new("StringValue") Vote.Name = "Vote" Vote.Parent = player Vote.Value = "NA" end) -- Prepare Pads for _, Pad in pairs(VotingSystem:GetChildren())do if Pad.Name ~= "VotingDisplay" then Pad.Touched:Connect(function(hit) if hit and hit.Parent and players:GetPlayerFromCharacter(hit.Parent) then local player = players:GetPlayerFromCharacter(hit.Parent) local plyrVote = player:WaitForChild("Vote") if plyrVote.Value ~= Pad.Name then Pad:WaitForChild("Votes").Value = Pad:WaitForChild("Votes").Value + 1 if plyrVote.Value ~= "NA" then local padToSubtract = VotingSystem:FindFirstChild(plyrVote.Value) if padToSubtract then padToSubtract:WaitForChild("Votes").Value = padToSubtract:WaitForChild("Votes").Value - 1 end end plyrVote.Value = Pad.Name UpdateDisplay() end end end) end end while true do UpdateStatus("Intermission") WaitTime(0, 15) UpdateStatus("Voting In Progress") RandomizeMaps() WaitTime(0, 10) -- Declare Winning Map local mapWinner = CalculateWinner() -- Reset Pads ResetVotes() UpdateStatus("Loading Map "..mapWinner) wait(5) UpdateStatus("Round In Progress") WaitTime(minutes, seconds) UpdateStatus("Game Over!") wait(5) end
Additionally, I would be placing your maps under ServerStorage
or ReplicatedStorage
instead of Lighting
.