I can't seem to get a FireServer() to work

Alright, heres the scripts:

local script inside a gui


script.Parent.BackgroundColor3 = Color3.fromRGB(170, 0, 0)
script.Parent.Text = "OPTED OUT"
script.Parent.BackgroundTransparency = 0
local value = false
local de = true
local player = game.Players.LocalPlayer
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("sendopt")
script.Parent.MouseButton1Click:Connect(function(click)
	if de == true then
		de=false
		if script.Parent.Text == "OPTED OUT" and script.Parent.BackgroundColor3 == Color3.fromRGB(170, 0, 0) then
			script.Parent.Text = "OPTED IN"  
			script.Parent.BackgroundColor3 = Color3.fromRGB(0, 170, 0)
			value = true
			remoteEvent:FireServer()
			print("fired")
		else
			script.Parent.Text = "OPTED OUT"  
			script.Parent.BackgroundColor3 = Color3.fromRGB(170, 0, 0)
			value = false
			remoteEvent:FireServer()
			print("fired")
		end
		wait(4)
		de = true
	end
end)

serverscript, inside serverscriptservice

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local remoteFunction = ReplicatedStorage:WaitForChild("requestvalue")
local remoteFunctionrt = ReplicatedStorage:WaitForChild("requestnew")
local remoteEventopt = ReplicatedStorage:WaitForChild("sendopt")
local remoteEventwait = ReplicatedStorage:WaitForChild("waitinglol")
local remoteEventweare = ReplicatedStorage:WaitForChild("waiting")


local roundval = game.ServerScriptService.isround.Value
local function createPart(roundval)
	local roundval = game.ServerScriptService.isround.Value
	return roundval
end
local valuelol = game.ServerScriptService.new.Value
local function returnvals(valuelol)
	local valuelol = game.ServerScriptService.new.Value
	return valuelol	
end

local function changeopt(player)
	if  player:GetAttribute("Opted") == true then
		player:SetAttribute("Opted", false)
		print("false")
	else
		player:SetAttribute("Opted", true)
		print("true")
	end
end

local function plrwaiting(player)
	if  player:GetAttribute("playing") == true then
		player:SetAttribute("playing", false)
	else
		player:SetAttribute("playing", true)
	end
end

local function waitingbefore(player)
	for _, player in ipairs(game.Players:GetPlayers()) do
		if player:GetAttribute("playing") == true then
			script.waiitng.Value = script.waiitng.Value + 1
			local value = script.waiitng.Value
			remoteEventwait:FireAllClients(value)
			
end	
	end	
		end
local function wearewaiting(player)
	waitingbefore()
end

remoteFunction.OnServerInvoke = createPart
remoteFunctionrt.OnServerInvoke = returnvals
remoteEventopt.OnServerEvent:Connect(changeopt)
remoteEventwait.OnServerEvent:Connect(plrwaiting)
remoteEventweare.OnServerEvent:Connect(waitingbefore)

Heres just the important part in the serverscript:

local function changeopt(player)
	if  player:GetAttribute("Opted") == true then
		player:SetAttribute("Opted", false)
		print("false")
	else
		player:SetAttribute("Opted", true)
		print("true")
	end
end

the whole local script is important.
The print in the local script works just fine, while the print in the serverscript does not.
no errors
Thanks for your help!!

Make sure your if statements are going through because they don’t error if they are false. The best way to do that is to put a print() saying something and if it prints, it should be fine.

I think I did that;

local function changeopt(player)
	if  player:GetAttribute("Opted") == true then
		player:SetAttribute("Opted", false)
		print("false")
	else
		player:SetAttribute("Opted", true)
		print("true")
	end
end

I’m talking about in the local script. Did the text change when you ran the local script?

Ok, that also works. When I click it it fires the server and changes everything it should in the local script, it even prints. I not 100% sure but I think the error is in the server
saw your edit, it does change

Try moving this line above the other 2 lines.

What do you mean by that, sorry if its obvious

Sorry for the unclarity. I meant to move the 3rd line in this sequence and switch it with the top line.

Thanks for clarifying, there is an error

Unknown global ‘changeopt’

Okay. I think the problem is that the function is not running in the first place. The remote event if firing and is received but it is not reaching the function. Try making a print() on the first line of the function and see if it runs.

You are right, it is not firing.

This might work, but it will result in the script becoming a bit unorganized. Try changing that to remoteEventopt.OnServerEvent:Connect(function(plr)
changeopt(plr)
end)

The function is still not firing, still no errors. Sorry

Sorry I messed up typing the substitution. Instead, try this

remoteEventopt.OnServerEvent:Connect(function(plr)
if  player:GetAttribute("Opted") == true then
	player:SetAttribute("Opted", false)
	print("false")
else
	player:SetAttribute("Opted", true)
	print("true")
end
end)

and you can delete the function too

Heres the code I got:

remoteEventopt.OnServerEvent:Connect(function(player)
	print("hi")
	if  player:GetAttribute("Opted") == true then
		player:SetAttribute("Opted", false)
		print("false")
	else
		player:SetAttribute("Opted", true)
		print("true")
	end
end)

Is this corret? It does not print “hi”

That is very weird. I have no idea whets going on, but I’ll try to come back to this later if I can. Good luck.

Why are you trying to use FireServer on a local function?

Thanks for your help (character minimum)

Because I am trying to fire the server

You’re “Firing” the Server via a local function, everything needs to stay on the servers end first, before initiating anything that has to do with the client firing back to the FireServer call.