I’m working on a claimable house system where players can buy a house. Each house will have a sign with a proximity prompt that says "Buy House." Once purchased, the player will own the house and be able to lock/unlock the door. The sign will also display their avatar and username.
However, nothing works. The coins do not deduct from my leaderboard, and the info on the sign doesn’t update either.
I would really appreciate any help with this!
Sign Script.
local ProximityPrompt = script.Parent.ProximityPrompt
local SurfaceGui = script.Parent.SurfaceGui
local ProfileService = require(game.ServerScriptService.Modules.ProfileService)
local COST = 400
ProximityPrompt.Triggered:Connect(function(player)
if not ProfileService or not ProfileService.GetProfileAsync then
warn("ProfileService is not loaded or missing GetProfileAsync function!")
return
end
local profile = ProfileService.GetProfileAsync(player.UserId)
if not profile then
warn("Failed to retrieve profile for player: " .. player.UserId)
return
end
if profile.Coins < COST then
game:GetService("StarterGui"):SetCore("SendNotification", {
Title = "Insufficient Coins";
Text = "You do not have enough coins to purchase this.";
Duration = 3;
})
return
end
profile.Coins = profile.Coins - COST
SurfaceGui.NameLabel.Text = player.Name
SurfaceGui.AvatarImage.Image = "rbxthumb://type=AvatarHeadShot&id=" .. player.UserId .. "&w=100&h=100"
ProximityPrompt.Enabled = false
script.Parent:SetAttribute("Owner", player.UserId)
end)
Door Script:
local ProximityPrompt = script.Parent.ProximityPrompt
local ownerID = script.Parent.Parent.BuyHouseSign:GetAttribute("Owner")
local doorLocked = false
local function updateDoor(locked)
doorLocked = locked
ProximityPrompt.ActionText = locked and "Unlock" or "Lock"
script.Parent.Transparency = locked and 0 or 0.7
script.Parent.CanCollide = locked
end
ProximityPrompt.Triggered:Connect(function(player)
if player.UserId ~= ownerID then
player:warn("Only the house owner can lock/unlock this door.")
return
end
updateDoor(not doorLocked)
end)
If the issue lies with the profile service then this is what I have:
DataManagerScript
local Players = game:GetService("Players")
local serverScriptService = game:GetService("ServerScriptService")
local modules = serverScriptService:WaitForChild("Modules")
local ProfileService = require(modules:WaitForChild("ProfileService"))
local template = require(script:WaitForChild("Template"))
local leaderstats = require(script:WaitForChild("Leaderstats"))
local datakey = "_DataStore"
local profileStore = ProfileService.GetProfileStore(datakey, template).Mock
local dataManager = {}
dataManager.Profiles = {}
local function PlayerAdded(player: Player)
local profile = profileStore:LoadProfileAsync("Player_"..player.UserId)
if profile ~= nil then
profile:AddUserId(player.UserId)
profile:Reconcile()
profile:ListenToRelease(function()
dataManager.Profiles[player] = nil
player:Kick()
end)
if player:IsDescendantOf(Players) then
dataManager.Profiles[player] = profile
leaderstats:Create(player, profile)
else
profile:Release()
end
else
player:Kick()
end
end
local function PlayerRemoving(player: Player)
local profile = dataManager.Profiles[player]
if profile ~= nil then
profile:Release()
end
end
for _, player in Players:GetPlayers() do
task.spawn (PlayerAdded, player)
end
Players.PlayerAdded:Connect(PlayerAdded)
Players.PlayerRemoving:Connect(PlayerRemoving)
return dataManager
Instead of grabbing the player’s profile directly from the ProfileService module, why don’t you just get it from your cached table of profiles inside dataManager?
function dataManager.GetProfile(player)
if not player:IsDescendantOf(Players) then return end
local profile = dataManager.Profiles[player]
while profile == nil do
profile = dataManager.Profiles[player]
task.wait()
end
return profile
end
Put this function inside your dataManager module, require the dataManager module instead of ProfileService and get the player’s profile from there
Update: I got it working, but the issue is the money doesn’t deduct when buying the house.
Door Script:
local ProximityPrompt = script.Parent.ProximityPrompt
local SurfaceGui = script.Parent.SurfaceGui
local dataManager = require(game.ServerScriptService.Modules.DataManager)
local COST = 400
ProximityPrompt.Triggered:Connect(function(player)
local profile = dataManager.GetProfile(player)
if not profile then
warn("Failed to retrieve profile for player: " .. player.UserId)
return
end
if profile.Data.Coin < COST then
game:GetService("StarterGui"):SetCore("SendNotification", {
Title = "Insufficient Coin",
Text = "You do not have enough Coin to purchase this.",
Duration = 3,
})
return
end
profile.Data.Coin = profile.Data.Coin - COST
print(player.Name .. " has " .. profile.Data.Coin .. " Coin(s) remaining.") -- Debug
SurfaceGui.OwnerName.Text = player.Name
SurfaceGui.PlayerImage.Image = "rbxthumb://type=AvatarHeadShot&id=" .. player.UserId .. "&w=100&h=100"
ProximityPrompt.Enabled = false
script.Parent:SetAttribute("Owner", player.UserId)
end)
The script of the sign and the door are both client, but the Profileservice is all in ServerScriptService
The infinite yield of the proximity prompt comes from StarterPlayerScripts which has this script:
local ProximityPrompt = script.Parent:WaitForChild("ProximityPrompt")
local doorOwnerId = script.Parent.Parent:GetAttribute("Owner")
ProximityPrompt.Triggered:Connect(function(player)
if player.UserId == doorOwnerId then
if ProximityPrompt.ActionText == "Lock House" then
-- Lock the door: only the owner can enter
script.Parent.CanCollide = true
script.Parent.Transparency = 0
ProximityPrompt.ActionText = "Unlock House"
else
script.Parent.CanCollide = false
script.Parent.Transparency = 0.7
ProximityPrompt.ActionText = "Lock House"
end
end
end)
The proximity prompt isn’t being found, that is why it is giving that error. Try checking if it is in the right place.
Try this code, I didn’t check if it works because I wrote this on my phone, it just adds a save feature right after you purchase the house
local ProximityPrompt = script.Parent.ProximityPrompt
local SurfaceGui = script.Parent.SurfaceGui
local dataManager = require(game.ServerScriptService.Modules.DataManager)
local COST = 400
ProximityPrompt.Triggered:Connect(function(player)
local profile = dataManager.GetProfile(player)
if not profile then
warn("Failed to retrieve profile for player: " .. player.UserId)
return
end
if profile.Data.Coin < COST then
game:GetService("StarterGui"):SetCore("SendNotification", {
Title = "Insufficient Coin",
Text = "You do not have enough Coin to purchase this.",
Duration = 3,
})
return
end
profile.Data.Coin = profile.Data.Coin - COST
print(player.Name .. " has " .. profile.Data.Coin .. " Coin(s) remaining.") -- Debug
dataManager.SaveProfile(player, profile)
SurfaceGui.OwnerName.Text = player.Name
SurfaceGui.PlayerImage.Image = "rbxthumb://type=AvatarHeadShot&id=" .. player.UserId .. "&w=100&h=100"
ProximityPrompt.Enabled = false
script.Parent:SetAttribute("Owner", player.UserId)
end)
Forgive me for my late reply. I’ve had a hectic week. I attempted your code, and this is what I got in the output.
[ProfileService]: Roblox API services available - data will be saved - Server - ProfileService:2307
User has 0 Coin(s) remaining. - Server - Script:25
Infinite yield possible on 'Players.User.PlayerScripts:WaitForChild("ProximityPrompt")' - Studio
Stack Begin - Studio
Script 'Players.User.PlayerScripts.HousePurchaseClient', Line 1 - Studio - HousePurchaseClient:1
Stack End - Studio
The proximity prompt isn’t being found, that is why it is giving that error. Try checking if it is in the right place.
That script is in Starterplayerscripts. Perhaps I should specify it more where the prompt can be found initially? That proximity prompt is actually in workspace → Houses (folder) → Door (part) → Proximityprompt