Olli Tuominen
Olli Tuominen

Reputation: 1

Roblox Buyable area "wall door"

Basically i made a wall/door system that allows me to walk into it and the wall disappears. (It costs 1000 money which is used from the leaderboard). Problem is that the when someone has enough of money to buy the wall, yes it disappears and saves but it disappears for everybody which is not supposed to be happening and i cannot find solution for it.

script for door/wall is located under workspace.door.script and this is the script local door = script.Parent

-- Ensure "Locked" is an IntValue
local lockedValue = door:FindFirstChild("Locked")
if not lockedValue or not lockedValue:IsA("IntValue") then
    lockedValue = Instance.new("IntValue")
    lockedValue.Name = "Locked"
    lockedValue.Parent = door
end

local function purchaseDoor(player)
    local moneyValue = player.leaderstats and player.leaderstats:FindFirstChild("Money")
    if moneyValue and type(door.Requirement.Value) == "number" and moneyValue.Value >= door.Requirement.Value and lockedValue.Value == 0 then
        moneyValue.Value = moneyValue.Value - door.Requirement.Value
        door.Transparency = 0.5
        door.CanCollide = false
        lockedValue.Value = 1

        -- Save the "Locked" status using DataStore
        local DataStoreService = game:GetService("DataStoreService")
        local PurchaseDataStore = DataStoreService:GetDataStore("PurchaseDataStore")

        local key = "PurchaseStatus_" .. player.UserId
        local success, _ = pcall(function()
            PurchaseDataStore:SetAsync(key, 1)
        end)
    end
end

local function onTouched(hit)
    local player = game.Players:GetPlayerFromCharacter(hit.Parent)
    if player then
        purchaseDoor(player)
    end
end

door.Touched:Connect(onTouched)

local function onPlayerAdded(player)
    if player then
        -- Check and load the "Locked" status from DataStore
        local DataStoreService = game:GetService("DataStoreService")
        local PurchaseDataStore = DataStoreService:GetDataStore("PurchaseDataStore")

        local key = "PurchaseStatus_" .. player.UserId
        local success, savedLockedStatus = pcall(function()
            return PurchaseDataStore:GetAsync(key)
        end)

        if success and type(savedLockedStatus) == "number" and savedLockedStatus == 1 then
            lockedValue.Value = 1
            door.Transparency = 1 -- Set the transparency to 1 to make the door fully invisible
            door.CanCollide = false
        else
            lockedValue.Value = 0
            door.Transparency = 0-- Set the transparency back to 0 to make the door visible
            door.CanCollide = true
        end
    end
end

game.Players.PlayerAdded:Connect(onPlayerAdded)

then i have 3 scripts in serverscriptservice called PurchaseWallScript, Script and leaderstats.

This is PurchaseWallScript:

local DataStoreService = game:GetService("DataStoreService")
local PurchaseDataStore = DataStoreService:GetDataStore("PurchaseDataStore")

local door = workspace.Model.Model.Door

-- Ensure "Locked" is an IntValue
local lockedValue = door:FindFirstChild("Locked")
if not lockedValue or not lockedValue:IsA("IntValue") then
    lockedValue = Instance.new("IntValue")
    lockedValue.Name = "Locked"
    lockedValue.Parent = door
end

local function onPlayerAdded(player)
    local key = "PurchaseStatus_" .. player.UserId

    local success, savedPurchaseStatus = pcall(function()
        return PurchaseDataStore:GetAsync(key)
    end)

    if success and type(savedPurchaseStatus) == "boolean" then
        if savedPurchaseStatus then
            -- If the door is purchased, set the transparency to 1 to make it fully invisible
            door.Transparency = 1
            door.CanCollide = false
            lockedValue.Value = 1
        else
            -- If the door is not purchased, set the transparency back to 0.5 to make it visible
            door.Transparency = 0.5
            door.CanCollide = true
            lockedValue.Value = 0
        end
    end
end

local function onPlayerLeaving(player)
    local key = "PurchaseStatus_" .. player.UserId

    local success, _ = pcall(function()
        PurchaseDataStore:SetAsync(key, lockedValue.Value == 1) -- Save the locked status as a boolean
    end)
end

game.Players.PlayerAdded:Connect(onPlayerAdded)
game.Players.PlayerRemoving:Connect(onPlayerLeaving)

local function onTouched(hit)
    local player = game.Players:GetPlayerFromCharacter(hit.Parent)
    if player and lockedValue.Value == 0 then
        local moneyValue = player.leaderstats and player.leaderstats:FindFirstChild("Money")
        if moneyValue and type(door.Requirement.Value) == "number" and moneyValue.Value >= door.Requirement.Value then
            moneyValue.Value = moneyValue.Value - door.Requirement.Value
            door.Transparency = 1
            door.CanCollide = false
            lockedValue.Value = 1

            -- Save the "Locked" status using DataStore
            local key = "PurchaseStatus_" .. player.UserId
            local success, _ = pcall(function()
                PurchaseDataStore:SetAsync(key, true)
            end)
        else
            print("Not enough money to buy the door.")
        end
    end
end

door.Touched:Connect(onTouched) 

this is Script:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ResetDoorStatusEvent = ReplicatedStorage:WaitForChild("ResetDoorStatusEvent")
local door = workspace.Model.Model.Door

ResetDoorStatusEvent.OnServerEvent:Connect(function(player)
    if player then
        local lockedValue = door:FindFirstChild("Locked")
        if lockedValue and lockedValue:IsA("IntValue") then
            lockedValue.Value = 0 -- Set the "Locked" status to 0 (unlocked)
            door.Transparency = 0.50 -- Set the door's transparency back to 0 (fully visible)
            door.CanCollide = true -- Set the door to be collidable again
        end
    end
end)

This is leaderstats:

local DataStoreService = game:GetService("DataStoreService")
local MoneyDataStore = DataStoreService:GetDataStore("MoneyDataStore")

local players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local moneyPerSecond = 0

local function saveMoney(player, moneyValue)
    local success, error = pcall(function()
        MoneyDataStore:SetAsync(tostring(player.UserId), moneyValue)
    end)
    if not success then
        warn("Error saving money for player " .. player.Name .. ": " .. error)
    end
end

local function giveMoney(player)
    local leaderstats = player:FindFirstChild("leaderstats")
    local moneyValue = leaderstats and leaderstats:FindFirstChild("Money")

    if not leaderstats then
        leaderstats = Instance.new("Folder")
        leaderstats.Name = "leaderstats"
        leaderstats.Parent = player
    end
    if not moneyValue then
        moneyValue = Instance.new("IntValue")
        moneyValue.Name = "Money"
        moneyValue.Parent = leaderstats

        -- Load the player's saved money if it exists
        local savedMoney = MoneyDataStore:GetAsync(tostring(player.UserId))
        if savedMoney then
            moneyValue.Value = savedMoney
        else
            -- Create a new saved money value if it doesn't exist
            local newSavedMoney = Instance.new("IntValue")
            newSavedMoney.Name = "SavedMoney"
            newSavedMoney.Parent = player
        end
    end

    -- Create a coroutine to update and save the money every second
    coroutine.wrap(function()
        while true do
            wait(1) -- Wait for 1 second
            if player and player:IsDescendantOf(players) then
                moneyValue.Value = moneyValue.Value + moneyPerSecond
                saveMoney(player, moneyValue.Value) -- Save the money using DataStore

                -- Send the updated money value to the client using a RemoteEvent
                local remoteEvent = ReplicatedStorage:FindFirstChild("MoneyChangedEvent")
                if remoteEvent then
                    remoteEvent:FireClient(player, moneyValue.Value)
                end
            else
                break -- Stop the loop if the player leaves
            end
        end
    end)()
end

local function onPlayerAdded(player)
    -- Start giving money
    giveMoney(player)
end

players.PlayerAdded:Connect(onPlayerAdded)

I also have reset button for the wall/door so i can test it. dont think its necessary to share but here it is. its located in StarterGui

local button = script.Parent

button.MouseButton1Click:Connect(function()
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local ResetDoorStatusEvent = ReplicatedStorage:WaitForChild("ResetDoorStatusEvent")

    local player = game.Players.LocalPlayer
    if player then
        ResetDoorStatusEvent:FireServer(player)
    end
end)

Purpose is to walk to the wall/door when you have enough money and then it disappears and you are able to walk through. results are that its working and saving but the wall/door disappears for everybody when someone buys it which is not supposed to be happening.

Upvotes: 0

Views: 111

Answers (1)

Buzzyy
Buzzyy

Reputation: 121

There are quite a few types of scripts in Roblox, but the two you'll most often use are LocalScripts and Scripts.

LocalScripts are run on the client, meaning that what happens only happens on the person who ran it's computer, while Scripts run on the server, meaning that anyone in that server will see a change.

Some things you can only access on LocalScripts and some you can only access on Scripts.

Your issue here is that you are making the door dissapear on the server. What you need to do is create a RemoteEvent that the server fires to the player when it knows that the player can access it, and then opens the door on the client.

Upvotes: 0

Related Questions