this is some voodoo ahh functionality
basically,
i have settings right??
yeah and those settings get saved very nicely and stuff, except for ONE setting
the setting being Show Crosshair
, for whatever reason the value of it is the settings table
setting it to true seems to fix it on the server, but for whatever reason
the client converts it into the settings table and i don’t know why
so we know that the client is the issue, but how is this possible??
i’m just going to drop you the code:
server side:
function InitializePlayerData(plr: Player)
local totalKills = GetOrCreateAttribute(plr, "TotalKills", 0)
local totalDeaths = GetOrCreateAttribute(plr, "TotalDeaths", 0)
local totalCurrencyEarned = GetOrCreateAttribute(plr, "TotalCurrencyEarned", 0)
local totalXpEarned = GetOrCreateAttribute(plr, "TotalXpEarned", 0)
local currentLevel = GetOrCreateAttribute(plr, "CurrentLevel", 1)
local currentWhisper = GetOrCreateAttribute(plr, "CurrentWhisper", 0)
-- 'Whisper' is basically a rebirth, but with an edgy name
-- so think of 'Whisper' as 'Rebirth' if you find it easier
local success, result = pcall(function()
return playerDataStorage:GetAsync(plr.UserId)
end)
if not success then
warn("Failed to fetch " .. plr.UserId .. "'s data!")
warn("Error log: " .. result)
result = nil
end
if not playerDataTable[plr.UserId] then
-- Set data;
playerDataTable[plr.UserId] = {
TotalKills = totalKills,
TotalDeaths = totalDeaths,
TotalCurrencyEarned = totalCurrencyEarned,
TotalXpEarned = totalXpEarned,
CurrentLevel = currentLevel,
CurrentWhisper = currentWhisper,
Settings = {
-- Default values
["Field of View"] = 90,
["Classic Aim Down Sights"] = false,
["Vitals GUI Color"] = Color3.fromRGB(255,255,255),
["Weapon GUI Color"] = Color3.fromRGB(255,255,255),
["Visible Viewmodel"] = true,
["Show Crosshair"] = true,
["First Person Tracers"] = true
}
}
end
if result then
playerDataTable[plr.UserId].TotalKills = result.TotalKills or totalKills
playerDataTable[plr.UserId].TotalDeaths = result.TotalDeaths or totalDeaths
playerDataTable[plr.UserId].TotalCurrencyEarned = result.TotalCurrencyEarned or totalCurrencyEarned
playerDataTable[plr.UserId].TotalXpEarned = result.TotalXpEarned or totalXpEarned
playerDataTable[plr.UserId].CurrentLevel = result.CurrentLevel or currentLevel
playerDataTable[plr.UserId].CurrentWhisper = result.CurrentWhisper or currentWhisper
local vitalsGuiColorDeserialized = Deserialize(result.Settings["Vitals GUI Color"])
local weaponGuiColorDeserialized = Deserialize(result.Settings["Weapon GUI Color"])
for setting, value in pairs(result.Settings) do
playerDataTable[plr.UserId].Settings[setting] = value
end
warn(playerDataTable[plr.UserId].Settings["Show Crosshair"])
result.Settings["Vitals GUI Color"] = vitalsGuiColorDeserialized
result.Settings["Weapon GUI Color"] = weaponGuiColorDeserialized
end
returnPlayerSettings:FireClient(plr, playerDataTable[plr.UserId].Settings)
end
function OnSettingsReceived(plr: Player, setting: string, value: any)
if not table.find(validSettings, setting) then plr:Kick("Don't do that") return end
if cooldowns[plr.Name] then plr:Kick("That's very bad behavior") return nil end
cooldowns[plr.Name] = true
if not playerDataTable[plr.UserId] then
-- If player data isn't found, then initialize it;
InitializePlayerData(plr)
end
-- Update that value!
playerDataTable[plr.UserId].Settings[setting] = value
-- Some sort of warning that's here specifically for debugging :^)
warn(plr.Name .. " changed " .. setting .. " to " .. tostring(value))
warn("Current settings of " .. plr.Name .. " are: ")
print(playerDataTable[plr.UserId].Settings)
task.wait(0.1)
cooldowns[plr.Name] = false
end
function SaveData()
for userId, data in pairs(playerDataTable) do
local success, result = pcall(function()
local key = tostring(userId)
-- These 2 values here are for serializing the color data
-- because you can't store color3 values in datastores
local vitalsGuiColor = data.Settings["Vitals GUI Color"]
local weaponGuiColor = data.Settings["Weapon GUI Color"]
local vitalsGuiColorSerialized = Serialize(vitalsGuiColor)
local weaponGuiColorSerialized = Serialize(weaponGuiColor)
playerDataStorage:UpdateAsync(key, function(oldData)
oldData = oldData or {} -- No current data will instead initialize an empty table :^)
local newData = {
TotalKills = data.TotalKills,
TotalDeaths = data.TotalDeaths,
TotalCurrencyEarned = data.TotalCurrencyEarned,
TotalXpEarned = data.TotalXpEarned,
CurrentLevel = data.CurrentLevel,
CurrentWhisper = data.CurrentWhisper,
Settings = data.Settings
}
newData.Settings["Show Crosshair"] = true
newData.Settings["Vitals GUI Color"] = Serialize(newData.Settings["Vitals GUI Color"])
newData.Settings["Weapon GUI Color"] = Serialize(newData.Settings["Weapon GUI Color"])
return newData
end)
end)
if not success then
warn("Failed to save " .. userId .. "'s data!")
warn("Error information: ")
warn(result)
continue -- Skips to the next iteration so that print
-- below doesn't run
end
print("Successfully saved data for " .. userId)
end
end
client side
playerSettings.SettingChanged = function(setting: string, value: any)
if cooldown then return end
cooldown = true
if setting == "Field of View" then
-- This should hopefully work without issues
if value > 110 then value = 110 end
print("Field of view changed to: " .. value)
elseif setting == "Classic Aim Down Sights" then
-- Need to apply some sort of value here
print("The value of " .. setting .. " is now ", value)
elseif setting == "Vitals GUI Color" then
-- Now we loop through the screen guis and find 'PlayerHUD'
-- Indentations and nested for loops warning :(
for _,element in plrGui:GetChildren() do
if element.Name ~= "PlayerHUD" then continue end
-- Then we loop through the descendants of PlayerHUD and
-- Recolor the image labels to the color given
for _, toRecolor in element:GetDescendants() do
if not toRecolor:IsA("ImageLabel") then continue end
toRecolor.ImageColor3 = value
end
end
elseif setting == "Weapon GUI Color" then
-- Same as in vitals GUI recoloring
for _, element in plrGui:GetChildren() do
if element.Name ~= "Weapons" then
for _, toRecolor in element:GetDescendants() do
if not toRecolor:IsA("ImageLabel") then continue end
toRecolor.ImageColor3 = value
end
end
end
elseif setting == "Visible Viewmodel" then
print("The value of " .. setting .. " is now ", value)
local viewmodelsFolder = rStorage:WaitForChild("Viewmodels")
if value == true then
for _, basePart in viewmodelsFolder:GetDescendants() do
if not basePart:IsA("BasePart") then continue end
basePart.Transparency = 1
end
else -- If it's false instead
for _, basePart in viewmodelsFolder:GetDescendants() do
if not basePart:IsA("BasePart") then continue end
basePart.Transparency = 0
end
end
elseif setting == "Show Crosshair" then
-- Same as in viewmodel and ads, some value
print("The value of " .. setting .. " is now ", value)
elseif setting == "First Person Tracers" then
print("The value of " .. setting .. " is now ", value)
end
-- After the clusterbomb of elseif statements, it is time to
-- send the setting and the value to the server
sendPlayerSettings:FireServer(setting, value)
task.wait(0.1)
cooldown = false
end
local function InitializeSettings(data: any)
warn(playerSettings) -- show crosshair is true here
for setting, value in pairs(data) do
playerSettings:UpdateSetting(setting, data)
end
end
returnPlayerSettings.OnClientEvent:Connect(InitializeSettings)
-- All of the values written in here are default values;
local playerSettings = {
["Field of View"] = 90,
["Classic Aim Down Sights"] = false,
["Vitals GUI Color"] = Color3.fromRGB(255,255,255),
["Weapon GUI Color"] = Color3.fromRGB(255,255,255),
["Visible Viewmodel"] = true,
["Show Crosshair"] = true,
["First Person Tracers"] = true,
["Show Blood"] = true,
["SettingChanged"] = nil :: ((string, any) -> (nil))? -- Actually a callback
-- Thanks to that guy on the devforum for telling me this :^)
}
function playerSettings:GetSetting(name: string)
return self[name]
end
function playerSettings:UpdateSetting(name: string, value: any)
self[name] = value
playerSettings.SettingChanged(name, value)
end
return playerSettings
this is the output:
the big table is printed on the client before initiating anything
but then for whatever reason it just gets set to a table??