-
What do you want to achieve? Keep it simple and clear!
I’d like to build a potion shop system that lets the player purchase a potion from a GUI only if the player owns less than 5 of the ‘type’ of potion they’re trying to purchase, and then send a specific key back to the client to update the Text on the UI
Please note that I’m using a StringValue called ‘Type’ to put potions into categories, each potion has this StringValue to identify it’s type.
2. What is the issue? Include screenshots / videos if possible!
Assuming player owns 0 tools, The logic of the script works and the 1st potion of any ‘type’ can be purchased with enough ‘Points’, however, after 2nd potion is attempted to be bought of the same ‘Type’, the script doesn’t seem to be looping through the allPotions list correctly and it ends up sending a ‘nil’ response back to the local script, however after purchasing the first potion of let’s say ‘Health’ ‘type’, a potion with a ‘type’ of ‘Speed’ will be bought fine 2nd time around or if you bought potion of type ‘Defence’ and try to buy a potion of type ‘Health’, it works. (basically, can’t buy the same potion type more than once in a row)
3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I couldn’t find any relevant information about this issue.
I have done some testing and it doesn’t look like the script wants to carry on with the logic after the specificPotionType.Value is compared with potionType, and returns ‘Nil’ back to the local scripts (there are 9 local scripts, 1 for each button in the UI), I have put a print statement after the if i == #allPotions then to see if the script gets this far and continues running after the entire player backpack is checked, but it doesn’t, it just returns ‘Nil’ to the local scripts, I’d expect it to carry on with the algorithm honestly… I don’t see why it wouldn’t.
Here’s a link to a video to showcase the output and the GUI: IssueWithBuyingPotions.mp4 - Google Drive ,note that the buttons are a little glitchy due to the wait statements in the server script, trying to understand how to use the debounce with remote functions as it’s my first time using them: (Please note that the quality of the video will be poor during the first hour or 2 of this post going live as google drive has to process the video properly)
1 of the local scripts (other 8 only differ in print statements, buttons that are pressed and remote functions)
-- LOCAL SCRIPT
local replicatedStorage = game:GetService("ReplicatedStorage")
local shopEvents = replicatedStorage:WaitForChild("ShopEvents")
local buyPotionEvents = shopEvents:FindFirstChild("BuyPotionEvents")
local buySmallHealth = buyPotionEvents:FindFirstChild("BuySmallHealth")
local buyButton = script.Parent
local player = game.Players.LocalPlayer
buyButton.MouseButton1Click:Connect(function()
local returnValue = buySmallHealth:InvokeServer(player)
print(returnValue)
if returnValue == 1 then
buyButton.Text = "Bought!"
wait(2)
buyButton.Text = "Buy: 50 Points"
elseif returnValue == 2 then
buyButton.Text = "Not enough Points"
wait(2)
buyButton.Text = "Buy: 50 Points"
elseif returnValue == 3 then
buyButton.Text = "Max number of this item type owned"
wait(2)
buyButton.Text = "Buy: 50 Points"
end
end)
------------------------------------
--SERVER SCRIPT
local replicatedStorage = game:GetService("ReplicatedStorage") -- assigning ReplicatedStorage service to a variable
local serverStorage = game:GetService("ServerStorage") -- assigning ServerStorage service to a variable
local potionsFolder = serverStorage:WaitForChild("Potions") -- assigning the folder containing all the potions (tools) to a variable
local shopEvents = replicatedStorage:WaitForChild("ShopEvents") -- assigning the folder containing child folders
local buyPotionsEvents = shopEvents:WaitForChild("BuyPotionEvents") -- assigning the folder containing all RemoteFunctions to a variable
-----------------
local smallHealthPotion = potionsFolder:FindFirstChild("Small Health Potion")
local smallSpeedPotion = potionsFolder:FindFirstChild("Small Speed Potion")
local smallDefencePotion = potionsFolder:FindFirstChild("Small Defence Potion")
local mediumHealthPotion = potionsFolder:FindFirstChild("Medium Health Potion")
local mediumSpeedPotion = potionsFolder:FindFirstChild("Medium Speed Potion")
local mediumDefencePotion = potionsFolder:FindFirstChild("Medium Defence Potion")
local LargeHealthPotion = potionsFolder:FindFirstChild("Large Health Potion")
local LargeSpeedPotion = potionsFolder:FindFirstChild("Large Speed Potion")
local LargeDefencePotion = potionsFolder:FindFirstChild("Large Defence Potion")
-- assigning all the Potions (tools) to local variables
-----------------
local buySmallHealthPotion = buyPotionsEvents:FindFirstChild("BuySmallHealth")
local buySmallSpeedPotion = buyPotionsEvents:FindFirstChild("BuySmallSpeed")
local buySmallDefencePotion = buyPotionsEvents:FindFirstChild("BuySmallDefence")
local buyMediumHealthPotion = buyPotionsEvents:FindFirstChild("BuyMediumHealth")
local buyMediumSpeedPotion = buyPotionsEvents:FindFirstChild("BuyMediumSpeed")
local buyMediumDefencePotion = buyPotionsEvents:FindFirstChild("BuyMediumDefence")
local buyLargeHealthPotion = buyPotionsEvents:FindFirstChild("BuyLargeHealth")
local buyLargeSpeedPotion = buyPotionsEvents:FindFirstChild("BuyLargeSpeed")
local buyLargeDefencePotion = buyPotionsEvents:FindFirstChild("BuyLargeDefence")
local db = true
-- assigning all the remote functions to local variables
-----------------
local function potionBought(player,potion,potionType,potionCost) -- local function being fed information
clonePotion = potion:Clone() -- cloning a tool that the player wishes to buy and assigned it to a global variable
local leaderstats = player:WaitForChild("leaderstats") -- leaderstats is a folder that holds the IntValues that are used and displayed for the player to showcase their 'Points'
local points = leaderstats:FindFirstChild("Points") -- IntValue used to keep track of Points that players own, used to purchase items
local allPotions = player.Backpack:GetChildren() -- getting all tools that the players own into a table
if points.Value >= potionCost and #allPotions > 0 then -- check if the player can afford the potion and ensure that they at least own 1 item to avoid an empty allPotions table breaking the logic
local numberOfPotion = 0 -- this variable will be used to keep track of how many potions of the 'type' the player wants to buy currently owns
for i, specificPotion in pairs(allPotions) do -- for loop to check each potion (tool) in the allPoints list
local specificPotionType = specificPotion:FindFirstChild("Type") -- finding the current potion's 'type' that is currently being checked from the list (the value of this variable should be replaced after each check)
print("This is the type of potion in the list: ",specificPotionType.Value)
print("This is the type of potion that the player is attempting to buy: ",potionType)
if specificPotionType.Value == potionType then -- comparing the 'type' of potion from the list (potion player owns) and the type of the potion the player is trying to buy
numberOfPotion = numberOfPotion + 1 -- if the potion type the player wishes to buy is the same type as the potion that is being checked from the list, add +1 to the variable
else
numberOfPotion = numberOfPotion + 0
if i == #allPotions then -- waits until all items player owns have been looked through, then proceeds
print("Managed to get this far into the logic")
if numberOfPotion >= 5 then -- if the final value is greater or equal to 5 (player owns 5 or more potions of the same type as the one they wish to buy)
print("max item of this type owned")
message = 3 -- message variable hold a specific key number that will be fed back to the calling variable, will be used to determine what the client will see in text format in UI
return message -- returns the value of message back to the variable that has called the function
elseif numberOfPotion < 5 then -- if the final value is lower than 5 (player owns less than 5 of the same type of potion they wish to buy)
print("enough points")
points.Value = points.Value - potionCost -- remove the points it costs to buy the potion from the 'Points' variable
clonePotion.Parent = player.Backpack -- assigning the parent of the potion that is bought to the player's backpack
message = 1 -- message variable hold a specific key number that will be fed back to the calling variable, will be used to determine what the client will see in text format in UI
return message -- returns the value of message back to the variable that has called the function
end
end
end
end
elseif points.Value >= potionCost and #allPotions == 0 then -- check if the player can afford the potion and ensure that they don't have any tools/items in the allPotions table
print("enough points")
points.Value = points.Value - potionCost -- remove the points it costs to buy the potion from the 'Points' variable
clonePotion.Parent = player.Backpack -- assigning the parent of the potion that is bought to the player's backpack
message = 1 -- message variable hold a specific key number that will be fed back to the calling variable, will be used to determine what the client will see in text format in UI
return message -- returns the value of message back to the variable that has called the function
else
print("not enough points")
message = 2 -- message variable hold a specific key number that will be fed back to the calling variable, will be used to determine what the client will see in text format in UI
return message -- returns the value of message back to the variable that has called the function
end
end
-----------------
buySmallHealthPotion.OnServerInvoke = function(player) -- defining the Remote Function call from the client to a function
if db == true then -- using the bounce to attempt to give a cooldown on the amount of requests that can be sent through (which isn't working at the moment)
db = false
local message = potionBought(player, smallHealthPotion, "Health", 50) -- player is the player name, then the variable referencing the potion that will be bought, potion type, and potion cost
return message -- message variable hold a specific key number that will be fed back to the calling variable in a local script, this will determine what the client will see in text format in UI
elseif db == false then -- if cooldown is currently true, force the request to be held captive until the cooldown is up
wait(2)
db = true
end
end
buyMediumHealthPotion.OnServerInvoke = function(player)
if db == true then
db = false
local message = potionBought(player, mediumHealthPotion, "Health", 100) -- player is the player name, then the variable referencing the potion that will be bought, potion type, and potion cost
return message
elseif db == false then
wait(2)
db = true
end
end
buyLargeHealthPotion.OnServerInvoke = function(player)
if db == true then
db = false
local message = potionBought(player, LargeHealthPotion, "Health", 150) -- player is the player name, then the variable referencing the potion that will be bought, potion type, and potion cost
return message
elseif db == false then
wait(2)
db = true
end
end
buySmallSpeedPotion.OnServerInvoke = function(player)
if db == true then
db = false
local message = potionBought(player, smallSpeedPotion, "Speed", 25) -- player is the player name, then the variable referencing the potion that will be bought, potion type, and potion cost
return message
elseif db == false then
wait(2)
db = true
end
end
buyMediumSpeedPotion.OnServerInvoke = function(player)
if db == true then
db = false
local message = potionBought(player, mediumSpeedPotion, "Speed", 50) -- player is the player name, then the variable referencing the potion that will be bought, potion type, and potion cost
return message
elseif db == false then
wait(2)
db = true
end
end
buyLargeSpeedPotion.OnServerInvoke = function(player)
if db == true then
db = false
local message = potionBought(player, LargeSpeedPotion, "Speed", 75) -- player is the player name, then the variable referencing the potion that will be bought, potion type, and potion cost
return message
elseif db == false then
wait(2)
db = true
end
end
buySmallDefencePotion.OnServerInvoke = function(player)
if db == true then
db = false
local message = potionBought(player, smallDefencePotion, "Defence", 50) -- player is the player name, then the variable referencing the potion that will be bought, potion type, and potion cost
return message
elseif db == false then
wait(2)
db = true
end
end
buyMediumDefencePotion.OnServerInvoke = function(player)
if db == true then
db = false
local message = potionBought(player, mediumDefencePotion, "Defence", 100) -- player is the player name, then the variable referencing the potion that will be bought, potion type, and potion cost
return message
elseif db == false then
wait(2)
db = true
end
end
buyLargeDefencePotion.OnServerInvoke = function(player)
if db == true then
db = false
local message = potionBought(player, LargeDefencePotion, "Defence", 150) -- player is the player name, then the variable referencing the potion that will be bought, potion type, and potion cost
return message
elseif db == false then
wait(2)
db = true
end
end
-----------------
-----------------
-----------------