Making a claimable house system (issue with module script)

Hi,

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! :slight_smile:

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) 

image

1 Like

If the issue lies with the profile service then this is what I have:

image

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 

Does the output gives some information like warnings? Or it’s clear as the sky?

It throws this error in the output and it’s from the script in BuyHouseSign

ProfileService is not loaded or missing GetProfileAsync function! - Server - BuyHouseSign:8 

Can you share ProfileService script if you don’t mind anything? It would be useful and probably the core cause of the issue.

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

It’s the exact same one I got online :slight_smile:

I must be doing something wrong. Where do I put this line of code in the datamanager?

Anywhere. It’s a function. It just needs to be before you call it.

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) 
1 Like

Does it print the (player.Name .. " has " .. profile.Data.Coin .. " Coin(s) remaining.") -- Debug

Yes, it says "username has 0 Coin(s) remaining. "

Have you got the required amount of money? Did you check the right data?

Yea. For example if I have 800 coins then it will show “400 coins remaining” after buying the house.

The other thing that shows up in output as well is
Infinite yield possible on 'Players.User.PlayerScripts:WaitForChild("ProximityPrompt")

Which script is this reffering to?

EDIT: I realised one of the problems. (maybe) Is this code on the client or the server?

The script of the sign and the door are both client, but the Profileservice is all in ServerScriptService
image

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) 
1 Like

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 money still doesn’t deduct in leader stats.

1 Like

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

Then the proximity prompt needs to be directed to that.

So it would be:

local ProximityPrompt = workspace.Houses.Door.ProximityPrompt 

(change that over the line of code that says local ProximityPrompt = script.Parent:WaitForChild("ProximityPrompt")