Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

How to make a localscript save Money in the DataStorage?

Asked by 5 years ago

I am working on a small vehicle sim like game and trying to get my Local script to save the players their money on leaving the game so that when they come back they continue with the money they had when they did leave.

I just don't know how to get this done.

wait(3)

game.Players.LocalPlayer:WaitForChild("Data")
game.Players.LocalPlayer.Data.Stats:WaitForChild("Money")
game.Players.LocalPlayer:WaitForChild("Values")

MinSpeed = 15 --The player must be going faster than this in studs per second til they start earning money.

while wait(0.65) do
    if script.Parent == game:GetService("Players").LocalPlayer.Character then
    if game:GetService("Players").LocalPlayer.Values.CurrentVehicle.Value and game:GetService("Players").LocalPlayer.PlayerGui.Phone.PhoneBody.OS.AppFrames.Vehicles.Values.CurrentVehicle.Value.DriveSeat.Occupant and game:GetService("Players").LocalPlayer.PlayerGui.Phone.PhoneBody.OS.AppFrames.Vehicles.Values.CurrentVehicle.Value.DriveSeat.Occupant.Parent.Name == game:GetService("Players").LocalPlayer.Name then
        game:GetService("ReplicatedStorage").EarnMoney:InvokeServer()
    end
    end
end
1
Using DataStores should be done on the server side. As this code provided shows no use of it then I'm assuming you have never used it. You can learn here: https://developer.roblox.com/articles/Saving-player-data-using-PlayerDataStore xPolarium 1388 — 5y

2 answers

Log in to vote
0
Answered by 5 years ago

While xPolarium is right that the DataStore will only truly save values on the Server, this doesn't mean that you cant alter values on the Client to be saved, meaning you will require Remote Events / Functions.

Server Script

local DSS = game:GetService("DataStoreService")
local Storage = DSS:GetDataStore("Money")

local Players = game:GetService("Players")
local remote = game.ReplicatedStorage.EarnMoney

game.Players.PlayerAdded:Connect(function(player
    player:WaitForChild("Data")
    player.Data.Stats.Money.Value = Storage:GetAsync(player.UserId) or 0
    Storage:SetAsync(player.UserId, player.Data.Stats.Money.Value)
end)

game.Players.PlayerRemoving:Connect(function(player
    Storage:SetAsync(player.UserId, player.Data.Stats.Money.Value)
end)

remote.OnServerEvent:Connect(function(player, amount)
    player.Data.Stats.Money.Value = player.Data.Stats.Money.Value + amount
    Storage:SetAsync(player.UserId, player.Data.Stats.Money.Value)
end)

Local Script

local player = game.Players.LocalPlayer
local remote = game.ReplicatedStorage.EarnMoney

player:WaitForChild("Data")
player.Data.Stats:WaitForChild("Money")
player:WaitForChild("Values")

MinSpeed = 15 --The player must be going faster than this in studs per second til they start earning money.

while wait(0.65) do
    if script.Parent == player.Character then
        if player.Values.CurrentVehicle.Value and player.PlayerGui.Phone.PhoneBody.OS.AppFrames.Vehicles.Values.CurrentVehicle.Value.DriveSeat.Occupant and player.PlayerGui.Phone.PhoneBody.OS.AppFrames.Vehicles.Values.CurrentVehicle.Value.DriveSeat.Occupant.Parent.Name == player.Name then
            remote:FireServer(0) -- amount of money earned
        end
    end
end

I would actually change your EarnMoney to a Remote Event rather than a Remote Function for this, unless you need the callback, in which case change "Fire" and "Event" to "Invoke".

0
I recommend having the remote event and the datastore in separate scripts in case the datastore script gets messy as more is added as needed. Also, use sanity checks. Good answer Serpentine DesiredRep 75 — 5y
1
Don't do this as you're giving too much trust to the client. Sanity checks sure but a mechanic where you're checking for the occupant of vehicle can be kept on the server easily.You also fire the RemoteEvent in an infinite loop to SetAsync which can exceed data limits. Saving should only be done in specific moments. xPolarium 1388 — 5y
0
Sending DS requests for every single player every 0.65 seconds makes it super easy to hit the throttle limit, which can cause major data loss for the players in your game. To add, I think you have a typo; "player.PlayerGui.Phone.PhoneBody.OS.AppFrames.Vehicles.Values.CurrentVehicle.Val" appears twice in the same if statement on line 12. T0XN 276 — 5y
Ad
Log in to vote
0
Answered by 5 years ago
Edited 5 years ago

So I have made some changes here and there as none of those suggestions helped me fix the problem.

So I have some new code that I like to share that might be of better help in helping me out.

First of all I have a ServerScript and the first few lines are for the money a new player starts with.

game:WaitForChild("ReplicatedStorage")
vs = game:GetService("ReplicatedStorage"):WaitForChild("VehicleSpawns")
ps = game:GetService("ReplicatedStorage"):WaitForChild("VehiclePurchases")
remove = game:GetService("ReplicatedStorage"):WaitForChild("RemoveCar")
sell = game:GetService("ReplicatedStorage"):WaitForChild("SellCar")
em = game:GetService("ReplicatedStorage"):WaitForChild("EarnMoney")
respawn = game:GetService("ReplicatedStorage"):WaitForChild("Respawn")
rd = game:GetService("ReplicatedStorage"):WaitForChild("ResetData")
data = game:GetService("ReplicatedStorage"):WaitForChild("Load")
ba = game:GetService("ReplicatedStorage"):WaitForChild("BA")

function rd.OnServerInvoke(plr)
    if plr:FindFirstChild("Data") and plr:FindFirstChild("Stats") then
        for _,child in pairs (plr.Data.Stats:GetChildren()) do
            if child.ClassName == "BoolValue" then
                if child.Name == "Fiat 500 Purchased" then
                    child.Value = true
                else
                    child.Value = false
                end
            end
            if child.Name == "Money" or child.Name == "PendingMoney" then
                child.Value = 32000
            end
        end
    end
    plr:LoadCharacter()
end

function ba.OnServerInvoke(plr)
    local hum = nil
    for _,child in pairs (plr.Character:GetChildren()) do
        if child.Name == "Humanoid" or child.Name == "PhotoMode" then
            hum = child
        end
        if child.ClassName == "Accessory" then
            if hum.Sit == true then
            if child.Handle:FindFirstChild("BodyBackAttachment") then
                child.Handle.Transparency = 1
            end
            else
                if child.Handle:FindFirstChild("BodyBackAttachment") then
                child.Handle.Transparency = 0
                end
            end
        end
    end
end

function data.OnServerInvoke(player)
player:WaitForChild("Data")
player:WaitForDataReady()
repeat wait() until player:FindFirstChild("Data")
if player.DataReady then
if player:findFirstChild("Data") then
local score = player.Data.Stats:GetChildren()
for i = 1,#score do
local ScoreLoaded = player:LoadNumber(score[i].Name)
wait()
if ScoreLoaded ~= 0 then
score[i].Value = ScoreLoaded
end
end
end
else
    if player:FindFirstChild("PlayerGui") and player.PlayerGui:FindFirstChild("Notification") then
        player.PlayerGui.Notification:WaitForChild("LocalNotification").Value = "Failed to load data. Please rejoin immediately."
    end
end
end

function respawn.OnServerInvoke(plr)
   plr:LoadCharacter()
   print(plr.Name.." has respawned.")
end

function em.OnServerInvoke(plr)
   if plr:FindFirstChild("Data") and plr.Data:FindFirstChild("Stats") and plr.Data.Stats:FindFirstChild("Money") and plr.Data.Stats:FindFirstChild("PendingMoney") then
   local M = plr.Data.Stats.Money
   M.Value = M.Value + plr.Character.HumanoidRootPart.Velocity.Magnitude / 2.5
   wait(0.25)
   if plr.Data.Stats.Money.Value > plr.Data.Stats.PendingMoney.Value + 4500 then
    plr.Data.Stats.Money.Value = plr.Data.Stats.PendingMoney.Value
   end
   wait()
   plr.Data.Stats.PendingMoney.Value = plr.Data.Stats.Money.Value
   end
end

Then I do have another ServerScript that does store all my data

Alpha = true

function onPlayerEntered(newPlayer)
    if not newPlayer:FindFirstChild("Data") then
    local d = Instance.new("Configuration")
    d.Name = "Data"
    d.Parent = newPlayer

    local stats = Instance.new("Folder")
    stats.Name = "Stats"
    stats.Parent = d

    local cash = Instance.new("IntValue")
    cash.Name = "Money"
    cash.Parent = stats
    cash.Value = 32000

    local pcash = Instance.new("IntValue")
    pcash.Name = "PendingMoney"
    pcash.Parent = stats
    pcash.Value = cash.Value

    local lang = Instance.new("StringValue")
    lang.Parent = stats
    lang.Value = "English"
    lang.Name = "Language"

    local alpha = Instance.new("BoolValue")
    alpha.Name = "AlphaPlayer"
    alpha.Value = false
    if Alpha == true then
        alpha.Value = true
    end
    alpha.Parent = stats

for _,child in pairs (game.Lighting.Vehicles:GetChildren()) do
    if stats:FindFirstChild(child.Name.." Purchased") then

    else
        local I = Instance.new("BoolValue")
        I.Parent = stats
        I.Name = child.Name.." Purchased"
        if child.Name == "Fiat 500" then
        I.Value = true
    else
        I.Value = false
        end
    end
end

    end
end

function leaving(player)
    if player.ClassName == "Player" then
if player:FindFirstChild("Data") and player.Data:FindFirstChild("Stats") and player.Data.Stats:FindFirstChild("Money") and player:FindFirstChild("Values") and player.Values:FindFirstChild("Leaving") then
    local saving = false
if player.Data.Stats.Money.Value == 32000 then
    error("Failed to save "..player.Name.."'s Data")
else
    if saving == false then
        saving = true
local score = player.Data.Stats:GetChildren()
for i = 1,#score do
player:SaveNumber(score[i].Name,score[i].Value)
end
print("Successfully saved "..player.Name.."'s Data")
saving = false
    end
    end
end
end
end

game:GetService("Players").PlayerRemoving:connect(leaving)
game:GetService("Players").ChildAdded:connect(onPlayerEntered)

and then there is the make money script which was the first request which gives the player new money.

I would love it if the DataStores the vehicles the player does own and the money the player has and that as soon as the player leaves the game his stats are being saved and he is able to continue with those the first time he joins again.

Atm the vehicles and money is getting wiped and as soon as the player rejoins he starts back with 32k Cash and has no cars anymore.

I really do love the support you guys gave me so far and hopefully you guys are able to help me fix this.

0
I currently wanted to use the open sourced DataStore2 as I hoped that would solve my problem but it does not as well. DevBuildr 0 — 5y

Answer this question