What do you want to achieve?
Currently I am trying to make a shop where it grabs the players leaderstats info while also being able to grab the server storage service
What is the issue?
The issue that I am having right now is that the script cannot access the local player’s leaderstats but it can access server storage to grab the “ShopItems” folder right now because it is a server script, but if it is a local script it then cannot access the “ShopItems” folder but can access leaderstats
What solutions have you tried so far?
I have tried searching for solutions but I haven’t found anything that has been specifically for this problem im having
local player = game:GetService("Players").LocalPlayer or game.Players.LocalPlayer
script.Parent.MouseButton1Click:Connect(function()
if player.leaderstats.Points.Value >= game.ServerStorage.ShopItems[script.Parent.Name].Price.Value then
player.leaderstats.Points.Value -= game.ServerStorage.ShopItems[script.Parent.Name].Price.Value
game.ServerStorage.ShopItems[script.Parent.Name]:Clone().Parent = player.Backpack
end
end)
I used some tutorial code and I tried to update a lot of it to fit with what I was working with
The tutorial I used is below (The model I used to grab some of the scripts is also in the description)
This is how I have the GUI formatted
This is the Server Storage that contains the ShopItems folder
Sadly you cannot get the local player from a server script (you can use playeradded but in this situation remote events are more efficient), try using remote events or remote functions instead, you can ask me for help on that if you want.
Simple.
Make the script that gives them the items the main script (that’s what i’ll call it for now since i dont know what else to call it. Don’t forget to make an event for it though)
and then make the purchase button the script that fires it.
Here is a link that breaks down RemoteEvents if you need help.
I think I got it set up correctly but what if I am using a template to create an item that appears in the shop menu? And by that I mean that all the items that appear in the shop aren’t individual buttons. The template for the item grabs the Item’s name and price (the price is a value that is in the “ShopItems” folder in server storage) and then it gives the player the item while also taking away some points due to the purchase with the item’s corresponding price value located in the item without making having to create individual scripts for every item. (sorry if I didn’t explain it well, I’m not sure how else I can explain this method I am using)
Not sure if this would also help but here is what im trying to do with shop items, the image below shows new shop items however the shop items are not individual buttons hard coded in the game (or something like that).
The script creates a template using serverstorage to get the children of the tools in a folder called ShopItems to then create a clone of the template using the properties from the script to modify the template
I think I may need some more help with remote events and functions, could you help me out?
The past two messages I sent contain more of what I am trying to do if that helps.
--Clientside
local Remote = game:GetService("ReplicatedStorage"):WaitForChild("TestRemote")
local Button = .. -- Define a testbutton
Button.Activated:Connect(function()
local MessageToSend = "Hi, this is a message from the client!"
Remote:FireServer(MessageToSend)
end)
Remote.OnClientEvent:Connect(function(Message)
print(Message)
end)
--Serverside
local Remote = game:GetService("ReplicatedStorage"):WaitForChild("TestRemote")
Remote.OnServerEvent:Connect(function(Player, Message)
print(Message.." recieved from: "..Player.Name)
task.wait(5)
local AnotherMessage = "Server message only you can see "..Player.Name
Remote:FireClient(Player, AnotherMessage)
end)
So if I want to send the server a message that a player is purchasing a specific item would I just attach the variable that is being used to indicate the item being purchased to send a message to the server so it can grab the item and it’s price (the price is an IntValue inside of the item/tool) from server storage to then do its own thing from the Server side purchase script to purchase?
And if I do this then would I place it in the serverscript that clones the item/tool template so it has its own individual “FireClient” function when the template is clicked?
This is the script that I am using for the templates of items
local Item = game.ServerStorage.ShopItems:GetChildren()
for i = 1, #Item do
local NewItem = script:WaitForChild("Item"):Clone()
NewItem.Name = Item[i].Name
NewItem.Image = Item[i].TextureId
NewItem.ItemPrice.Text = "$"..Item[i].Price.Value
NewItem.ItemName.Text = Item[i].Name
NewItem.Parent = script.Parent
end
I am sorry if what I am trying to do doesn’t make sense, I’m not sure how else I could go about with explaining this. If there is something you want me to mention then tell me so I could help you get a better understanding with what I’m doing
Hi! let’s say you create buttons for each item in a store, then you could do
--Clientside
local Item = game:GetService("ReplicatedStorage"):WaitForChild("Items") -- Client does not have access to the ServerStorage, so instead have them in ReplicatedStorage
local Remote = game:GetService("ReplicatedStorage"):WaitForChild("Remote")
local ButtonTemplate = .. -- Define a template button, that we uses for our item buttons
for _, Item in pairs(Items:GetChildren()) do
local NewButton = ButtonTemplate:Clone()
-- Give the button details like Name, image ect. ect
local ButtonDebounce = false -- This makes a debounce for each button
NewButton.Activated:Connect(function()
Remote:FireServer(Button.Name) -- We use Button.Name as the itemType
end)
end
Then on the server, just check if the itemType sent from client is valid
Alright I am trying to add this into the game but I think I might be doing something wrong, I have the shop items folder in replicated storage and the script is the parent of the ImageButton (which is the item template that contains the price and name)
The script that is the parent of the template is a local script with this in the script
local Item = game:GetService("ReplicatedStorage"):WaitForChild("ShopItems")
local Remote = game:GetService("ReplicatedStorage"):WaitForChild("PurchaseItem")
local ButtonTemplate = script.Item
for _, Item in pairs(Item:GetChildren()) do
local NewItem = ButtonTemplate:Clone()
NewItem.Name = Item.Name
NewItem.Image = Item.TextureId
NewItem.ItemPrice.Text = "$"..Item.Price.Value
NewItem.ItemName.Text = Item.Name
local ButtonDebounce = false
NewItem.Activated:Connect(function()
Remote:FireServer(Item.Name)
end)
end
The template contains the ui elements shown in the image below
The Shop Items folder has the items with the prices on the inside of the tool, and the remote event is located in replicated storage as well
and for the purchase script, it is located in serverscriptservice but it doesn’t nothing because I still have to rescript it and I think the first script for the template buttons may be messed up because nothing shows up in the game when I load it. I am not sure if you mean that I should make separate buttons with separate scripts but I may have just interpreted your script incorrectly
Hi, At NewItem, you forgot to Parent the NewItem to the frame you have all your buttons. That should be after the Activated event, so that the button works as intended, before parenting.
It works now!
]
I still have one last question, how do I use the price IntValue from the tools to indicate the price that should be removed or checked in order to purchase an item in the purchase. Or should I just do it manually in the purchasing script
--Serverscript
local ItemsDataMS = require(game.ReplicatedStorage.ItemsModule)
Remote.OnServerEvent:Connect(function(Player, ItemType)
if not ItemType then return end
local ValidItemType = tostring(ItemType)
if not ValidItemType then return end
if not ItemsDataMS[ValidItemType] then return end
print("Client picked "..ValidItemType.." the cost of it is "..ItemsDataMS[ValidItemType]["Price"])
-- In other words "ItemsDataMS[ValidItemType]["Price"]" (if apple, means) ItemsDataMS["Apple"]["Price"], which gives the price of 35 in this case
end)
--Clientside
local ItemsDataMS = require(game:GetService("ReplicatedStorage"):WaitForChild("ItemsModule")) -- We use GetService & WaitForChild on client, to make sure both is present when running our script. It is already present on the server
for ItemName, ItemData in pairs(ItemsDataMS) do
local NewButton = ButtonTemplate:Clone()
local NewButton.Name = ItemName
local NewButton.TextPrice = ItemData["Price"] --Textlabel showing the price
--local NewButton.TextPrice = ItemsData[ValidItemType]["Price"] --This is the same result, just fetching the info another way which isn't needed in this case, but good to know that you can. It's the exactly same method as on the serverside.
-- Give the button details like image ect. ect
local ButtonDebounce = false -- This makes a debounce for each button
NewButton.Activated:Connect(function()
if ButtonDebounce then return end
ButtonDebounce = true
Remote:FireServer(ItemName) -- You can also use Button.Name. But since we have already defined ItemName above in the loop, we can use that as direct reference to the item we picked.
task.wait(1)
ButtonDebounce = false
end)
end
Hey! Sorry for the very late response, I think I have everything else working now besides the client side script. I keep getting errors that I am not sure how to fix and where they come from within the clientside script.
This is the script I have right now,
I also don’t know how to grab the item image is also something I am struggling with
local ItemsDataMS = require(game:GetService("ReplicatedStorage"):WaitForChild("ItemsModule")) -- We use GetService & WaitForChild on client, to make sure both is present when running our script. It is already present on the server
local ButtonTemplate = script.Item
local Remote = game:GetService("ReplicatedStorage")
for ItemName, ItemData in pairs(ItemsDataMS) do
local NewButton = ButtonTemplate:Clone()
NewButton.Name = ItemName
NewButton.Price = ItemData["Price"] --Textlabel showing the price
local ButtonDebounce = false -- This makes a debounce for each button
NewButton.Activated:Connect(function()
if ButtonDebounce then return end
ButtonDebounce = true
Remote:FireServer(ItemName) -- You can also use Button.Name. But since we have already defined ItemName above in the loop, we can use that as direct reference to the item we picked.
task.wait(1)
ButtonDebounce = false
end)
end
This is the error I see right now, and I don’t know how to fix it
I also updated the template which fixed one error but there is still the error with the price
Hi!
The error says that, there is no property named “Price” in ImageButton. Have you tried making a variable for your price, to see if this fixes the problem?