Scripts functions half of the time

Trying to make my own versions of DTI and wrote a script, but sometimes it doesn’t update the text or the camera.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local starsDataStore = DataStoreService:GetDataStore("PlayerStarsDataStore")

-- RemoteEvents
local UpdateCountdown = Instance.new("RemoteEvent", ReplicatedStorage)
UpdateCountdown.Name = "UpdateCountdown"

local TeleportEvent = Instance.new("RemoteEvent", ReplicatedStorage)
TeleportEvent.Name = "TeleportPlayers"

local SubmitVote = Instance.new("RemoteEvent", ReplicatedStorage)
SubmitVote.Name = "SubmitVote"

local SetExternalCamera = Instance.new("RemoteEvent", ReplicatedStorage)
SetExternalCamera.Name = "SetExternalCamera"

local DisableControls = Instance.new("RemoteEvent", ReplicatedStorage)
DisableControls.Name = "DisableControls"

-- Variables
local lobbyTime = 10  -- Lobby time in seconds
local gameTime = 5    -- Time for each player to walk the runway
local votingTime = 15 -- Voting duration
local themes = { "goth", "beach", "futuristic", "retro", "nature", "formal", "sporty", "fantasy" }
local playerVotes = {}

local function resetVotes()
	playerVotes = {}
	for _, player in pairs(Players:GetPlayers()) do
		playerVotes[player.UserId] = { score = 0, votes = 0 }
	end
end

local function loadPlayerStars(player)
	local playerKey = "Player_" .. player.UserId
	local success, stars = pcall(function()
		return starsDataStore:GetAsync(playerKey)
	end)

	if success and stars then
		player:SetAttribute("Stars", stars)
	else
		player:SetAttribute("Stars", 0)
	end
end

local function savePlayerStars(player)
	local playerKey = "Player_" .. player.UserId
	local stars = player:GetAttribute("Stars")

	local success, errorMessage = pcall(function()
		starsDataStore:SetAsync(playerKey, stars)
	end)

	if not success then
		warn("Failed to save stars for player " .. player.Name .. ": " .. errorMessage)
	end
end

-- Helper to teleport players to a specific location
local function teleportPlayers(location)
	for _, player in pairs(Players:GetPlayers()) do
		if player.Character and player.Character.PrimaryPart then
			print("Teleporting player " .. player.Name .. " to location: " .. location.Name)
			player.Character:SetPrimaryPartCFrame(location.CFrame)
		end
	end
end

local function setCameraToPart(camera, part)
	camera.CameraType = Enum.CameraType.Scriptable
	camera.CFrame = part.CFrame
end

local function startVoting()
	local votingSpawn = workspace:WaitForChild("VotingSpawn")
	teleportPlayers(votingSpawn)

	for _, player in pairs(Players:GetPlayers()) do
		print("Setting camera to voting spawn for player " .. player.Name)
		SetExternalCamera:FireClient(player) -- Tell client to use fixed camera
		local camera = workspace.CurrentCamera
		setCameraToPart(camera, votingSpawn)
	end
end

local function walkRunway(player)
	local runwayStart = workspace:WaitForChild("RunwayStart")
	local runwayEnd = workspace:WaitForChild("RunwayEnd")
	local runwayExit = workspace:WaitForChild("RunwayExit")

	DisableControls:FireClient(player, true)

	local character = player.Character
	local humanoid = character:FindFirstChildOfClass("Humanoid")

	-- Move player to the start of the runway
	print("Moving player " .. player.Name .. " to runway start")
	character:SetPrimaryPartCFrame(runwayStart.CFrame)
	task.wait(1)

	-- Move player along the runway
	humanoid:MoveTo(runwayEnd.Position)
	humanoid.MoveToFinished:Wait()

	-- Player reaches the end
	print("Player " .. player.Name .. " reached the runway end.")
	task.wait(2)  -- Wait for a bit

	humanoid:MoveTo(runwayExit.Position)
	humanoid.MoveToFinished:Wait()

	print("Player " .. player.Name .. " exited the runway.")
	DisableControls:FireClient(player, false)
end

-- Voting system handler
SubmitVote.OnServerEvent:Connect(function(player, stars)
	if playerVotes[player.UserId] then
		playerVotes[player.UserId].score = stars
		print("Player " .. player.Name .. " voted " .. stars .. " stars.")
	end
end)

-- Load stars when player joins
Players.PlayerAdded:Connect(function(player)
	loadPlayerStars(player)

	player.AncestryChanged:Connect(function(_, parent)
		if not parent then
			savePlayerStars(player)
		end
	end)
end)

-- Game loop
while true do
	wait(1)

	-- Lobby countdown
	for i = lobbyTime, 1, -1 do
		UpdateCountdown:FireAllClients("Lobby Time Left: " .. i .. " seconds")
		wait(1)
	end

	-- Game starts
	local theme = themes[math.random(1, #themes)]
	UpdateCountdown:FireAllClients("Game started! Theme: " .. theme .. ". Time left: " .. gameTime .. " seconds")
	teleportPlayers(workspace:WaitForChild("GameSpawn"))

	-- Game countdown
	for i = gameTime, 1, -1 do
		UpdateCountdown:FireAllClients("Game Time Left: " .. i .. " seconds")
		wait(1)
	end

	-- Start runway voting
	resetVotes()
	startVoting()

	for _, player in pairs(Players:GetPlayers()) do
		UpdateCountdown:FireClient(player, "Now voting for: " .. player.Name .. "!")
		walkRunway(player)
	end

	-- Enable Voting UI for all players at once
	for _, otherPlayer in pairs(Players:GetPlayers()) do
		otherPlayer.PlayerGui.VotingUI.Enabled = true
	end

	-- Wait for voting to finish
	wait(votingTime)

	-- Collect votes here before disabling UI
	for _, player in pairs(Players:GetPlayers()) do
		local lastVote = playerVotes[player.UserId] and playerVotes[player.UserId].score or 0
		print("Player " .. player.Name .. " last voted " .. lastVote .. " stars.")
	end

	-- Disable Voting UI for all players
	for _, otherPlayer in pairs(Players:GetPlayers()) do
		otherPlayer.PlayerGui.VotingUI.Enabled = false
	end

	-- Calculate and announce results
	local sortedPlayers = {}
	for userId, data in pairs(playerVotes) do
		table.insert(sortedPlayers, { userId = userId, score = data.score })
	end

	table.sort(sortedPlayers, function(a, b) return a.score > b.score end)

	local winnerMsg = "Results:\n"
	for i = 1, math.min(3, #sortedPlayers) do
		local playerName = Players:GetNameFromUserIdAsync(sortedPlayers[i].userId)
		winnerMsg = winnerMsg .. i .. ". " .. playerName .. " with " .. sortedPlayers[i].score .. " stars!\n"
	end
	UpdateCountdown:FireAllClients(winnerMsg)

	-- Pause before resetting
	wait(5)

	-- Reset for the next round
	resetVotes()
end

seems to have something to do with how the “SubmitVote” event is being sent if I’m correct. Can you send the script which triggers the remote?

1 Like

now reading the script again, it may have something to do with how the while loop works. I would not use a wait in the beginning of the loop, unless someone can prove me wrong

May I also ask why you’re using a “PlayerAdded” to load stars?

local buttons = {}  -- Table to hold references to the buttons
local defaultImage = "rbxassetid://4458881696"  -- Default image ID
local selectedImage = "rbxassetid://4458882827"  -- Selected image ID
local currentRating = 0  -- To track the current rating
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local SubmitVote = ReplicatedStorage:WaitForChild("SubmitVote")  -- RemoteEvent to submit votes

-- Reference your buttons by their specific names
for i = 1, 5 do
	local buttonName = "Star" .. i  -- Create "Star1", "Star2", etc.
	local button = script.Parent:WaitForChild(buttonName)
	table.insert(buttons, button)

	-- Function to change the button images based on selection
	local function onButtonClicked()
		-- Set the current rating to the clicked star index
		currentRating = i  -- This will refer to the current button in the loop

		-- Change all buttons according to the rating
		for j, btn in ipairs(buttons) do
			if j <= currentRating then
				btn.Image = selectedImage  -- Fill stars up to the clicked star
			else
				btn.Image = defaultImage  -- Reset to default image
			end
		end

		-- Send the vote to the server
		SubmitVote:FireServer(currentRating)  -- Send current rating to the server

		-- Disable UI after voting
		script.Parent.Parent.Enabled = false  -- Disable the voting UI
	end

	-- Function to handle mouse hover over stars
	local function onMouseEnter()
		-- Highlight the stars up to the hovered star temporarily
		for j, btn in ipairs(buttons) do
			if j <= i then
				btn.Image = selectedImage  -- Highlight
			else
				btn.Image = defaultImage  -- Reset to default image
			end
		end
	end

	-- Function to handle mouse leaving the stars
	local function onMouseLeave()
		-- Reset the stars to their current rating state
		for j, btn in ipairs(buttons) do
			if j <= currentRating then
				btn.Image = selectedImage  -- Fill stars up to the current rating
			else
				btn.Image = defaultImage  -- Reset to default image
			end
		end
	end

	-- Connect the functions to the button events
	button.MouseButton1Click:Connect(onButtonClicked)
	button.MouseEnter:Connect(onMouseEnter)
	button.MouseLeave:Connect(onMouseLeave)
end

-- Function to initialize star images based on the current rating
local function initializeStars()
	for i, btn in ipairs(buttons) do
		if i <= currentRating then
			btn.Image = selectedImage
		else
			btn.Image = defaultImage
		end
	end
end

-- Call the initialization function at the start
initializeStars()

I removed the wait, but I still experience issues with the camera and the countdown not updating at all. I use PlayerAdded to load player data when they join the game

I would prioritize the PlayerAdded first

other than that, I’m sorry I don’t understand the rest of this script.