Need help with shop script thing

it looks much better!
the script only runs once when initialized. since you created the event, and then disconnected it, you’d have to run the script again to get the event created again. perhaps it could look like this, roughly?:

local [VARIABLES] ...
local COOLDOWN = 3 --seconds
local inCooldown = false

-- function to cool down after event was completed
function InitCooldown1()
     task.wait(COOLDOWN)
     inCooldown = false
     InitPurchase1()
end

-- code to initialize event code
function InitPurchase1()
     if not inCooldown then             -- if not in the middle of cooling down...
           BuyEvent.OnServerEvent:Connect = function() ... -- initialize event
               [event code...]

               if [successful] then
                   BuyEvent:Disconnect()

                   inCooldown = true
                   InitCooldown1()
               end
          end
     end
end

-- make sure it runs AT SCRIPT INITIALIZATION so it can keep the loop going! :)
InitPurchase1()

though foxstream is right. you should probably make some server code that checks whether you can buy something or not, and then the server can give you the goods. it would be much easier for you to mess with later. the server stores all of the information for players anyways, so why not keep it there and compare there?

it also stops any clients from trying to hack/cheat their way into getting multiple items. they could edit the code (for the rare case the roblox client is hacked) and make it so that the server gives them any item, since the math for if they can afford it is on their side and they can fool the server. or better yet, find a way to make it break on the client side (which is much easier than in server-side) and have it duplicate as much as they want.

So something like this?

function initPurchase()
	PurchaseConnection2 = BuyItemEvent.OnServerEvent:Connect(function(Player,Item,CostOfItem)
		print("yes1")
		if Player.leaderstats.BaldiCoins.Value >= CostOfItem.Value then
			Player.PurchasedItem.Value = true
			Player.leaderstats.BaldiCoins.Value = Player.leaderstats.BaldiCoins.Value - CostOfItem.Value
			Player.ItemThatWasPurchased.Value = Item.Value
		end
		PurchaseConnection2:Disconnect()
	end)
end

yeah, check out my edited message above. it accidentally sent early when i pressed space + some other key.

Its giving me a unknown global for [successful]

maybe post the new code so i can see? yah?

I’m still trying to implement

local BuyItemEvent = game.ReplicatedStorage.ShopEvents:WaitForChild("ItemPurchased")
local BuyPerkEvent = game.ReplicatedStorage.ShopEvents:WaitForChild("PerkPurchased")
local PerkHandler = require(script.PerkHandler)
local PurchaseConnection2
local PurchaseConnection1
local Event = game.ReplicatedStorage.ShopEvents:WaitForChild("Time for shop to appear")

local COOLDOWN = 3 --seconds
local inCooldown = false

-- function to cool down after event was completed
function InitCooldown1()
	task.wait(COOLDOWN)
	inCooldown = false
	InitPurchase1()
end

-- code to initialize event code
function InitPurchase1()
	if not inCooldown then             -- if not in the middle of cooling down...
		BuyItemEvent.OnServerEvent = function(Player,Item,CostOfItem) -- initialize event
				print("yes1")
				if Player.leaderstats.BaldiCoins.Value >= CostOfItem.Value then
					Player.PurchasedItem.Value = true
					Player.leaderstats.BaldiCoins.Value = Player.leaderstats.BaldiCoins.Value - CostOfItem.Value
					Player.ItemThatWasPurchased.Value = Item.Value
				end

			if [successful] then
				BuyItemEvent:Disconnect()

				inCooldown = true
				InitCooldown1()
			end
		end
	end
end

-- make sure it runs AT SCRIPT INITIALIZATION so it can keep the loop going! :)
InitPurchase1()
	
function initPurchase1()

end

function initPurchase2()
	PurchaseConnection1 = BuyPerkEvent.OnServerEvent:Connect(function(Player,Perk,CostOfItem)
		print("yes2")
	if Player.leaderstats.BaldiCoins.Value >= CostOfItem.Value then
		Player.PurchasedPerk.Value = true
		Player.leaderstats.BaldiCoins.Value = Player.leaderstats.BaldiCoins.Value - CostOfItem.Value
		Player.PerkThatWasPurchased.Value = Perk.Value
		if Perk.Value ~= "Stamina Upgrade" then
			if Perk.Value == "Health Upgrade" then
				PerkHandler.Health_Upgrade(Player)
			end
		end
		else
			initPurchase2()
	end
		PurchaseConnection1:Disconnect()
	end)
end	


Event.OnServerEvent:Connect(initPurchase2)
Event.OnServerEvent:Connect(initPurchase1)

you shouldnot send the CostOfItem to the server as an exploiter can exploit it and send -99999999value and then he got 99999999 cash or even worse sending an -inf so he get inf cash

just see the 1st part about securing remotes

about the currency being subtracted twice try to move the subtract line to the top of the if statment

BuyPerkEvent.OnServerEvent:Connect(function(Player,Perk,CostOfItem)
	if Player.leaderstats.BaldiCoins.Value >= CostOfItem.Value then
		Player.leaderstats.BaldiCoins.Value = Player.leaderstats.BaldiCoins.Value - CostOfItem.Value
		Player.PurchasedPerk.Value = true
		Player.PerkThatWasPurchased.Value = Perk.Value
		if Perk.Value ~= "Stamina Upgrade" then
			if Perk.Value == "Health Upgrade" then
				PerkHandler.Health_Upgrade(Player)
			end
		end
	end	
end)

and you can remove ``if Perk.Value == "Health Upgrade" then" as its unnecessary and instead use

if Perk.Value ~= "Stamina Upgrade" and Perk.Value == "Health Upgrade" then
				PerkHandler.Health_Upgrade(Player)
		end

this doesnot have to do with the item being bought twice

if it still subtract the currency twice then add debounce that should fix it 100% if it still dotnot work then check if u copied ur script twice

and you should secure your remotes if you donot want players to get inf cash and buy your perks for free

1 Like

Its actually this from the client side script that runs more than once

BuyButtion.MouseButton1Click:Connect(function()
		if ButtionCooldown == false then
			ButtionCooldown = true
				if IsAItemSelectedValue.Value == true and PurchasedItem.Value == false and PressedButtion:GetAttribute("TypeofButtion") == "Item" then
					ButtionCooldown = true
					BuyItemEvent:FireServer(PressedButtion.ItemThatTheButtionsells)
					task.wait(0.2)
					if PurchasedItem.Value == true then
						BuyButtion.Text = "Item Purchased!"
						task.wait(2)
						BuyButtion.Text = "You already purchased a item you can't purchase another one!"
					else
						ButtionCooldown = true
						BuyButtion.Text = "Not Enough BaldiCoins!"
						task.wait(2)
						BuyButtion.Text = "Buy item"
						ButtionCooldown = false
				end
					task.wait(1)
					ButtionCooldown = false
					elseif IsAItemSelectedValue.Value == true and PurchasedPerk.Value == false and PressedButtion:GetAttribute("TypeofButtion") == "Perk" then
					ButtionCooldown = true
					BuyPerkEvent:FireServer(PressedButtion.PerkThatTheButtionsells)
					task.wait(0.2)
					if PurchasedPerk.Value == true then
						BuyButtion.Text = "Perk Purchased!"
						task.wait(2)
						BuyButtion.Text = "You already purchased a Perk you can't purchase another one!"
					else
						ButtionCooldown = true
						BuyButtion.Text = "Not Enough BaldiCoins!"
						task.wait(2)
						BuyButtion.Text = "Buy Perk"
						ButtionCooldown = false
					end
					task.wait(1)
					ButtionCooldown = false
			end
			task.wait(0.5)
			ButtionCooldown = false
		end	
	end)

( i was wrong about this i though of smt else sorry)

you are calling the functions only 1 time maybe your BuyPerkEvent and BuyItemEvent were sent to the server at the same time add a print statment after the buyitem and buy perk and see if both of them will output when u click

and check if the player`s coins in the leaderstats is bigger than the price before sending the event

Both of them doesn’t output at the same time its just that the buybuttion runs more than once even though it was clicked once

You can use math to calculate the needed subtraction of the currency.

Example:

local totalValue = 130
local costValue = 120

local calculation = totalValue - costValue

if calculation < 0 then
       return 0
else
       return calculation
end

add a if statment check to check if the player coins in the leaderstats is bigger than the object value in the local script and check if it was bought before

your script is long idk if you did that already

It does check to make sure the item is purchased

try adding a print statment to the purchased variable and see the output

and make the check for PurchasedItem.Value == false the first thing

IsAItemSelectedValue.Value == true and PurchasedItem.Value == false and PressedButtion:GetAttribute("TypeofButtion") == "Item"

Already did that

Perk/Item:  Health Upgrade  -  Server - ShopScript (ServerSide):6
  12:13:44.134  Item Cost:  250  -  Server - ShopScript (ServerSide):7
  12:13:44.134  Perk/Item:  Health Upgrade  -  Server - ShopScript (ServerSide):6
  12:13:44.135  Item Cost:  250  -  Server - ShopScript (ServerSide):7
  12:13:44.135  Perk/Item:  Health Upgrade  -  Server - ShopScript (ServerSide):6
  12:13:44.135  Item Cost:  250  -  Server - ShopScript (ServerSide):7
  12:13:44.136  Perk/Item:  Health Upgrade  -  Server - ShopScript (ServerSide):6
  12:13:44.136  Item Cost:  250  -  Server - ShopScript (ServerSide):7
  12:13:44.136  Perk/Item:  Health Upgrade  -  Server - ShopScript (ServerSide):6
  12:13:44.136  Item Cost:  250  -  Server - ShopScript (ServerSide):7
  12:13:44.137  Perk/Item:  Health Upgrade  -  Server - ShopScript (ServerSide):6
  12:13:44.137  Item Cost:  250  -  Server - ShopScript (ServerSide):7
  12:13:44.137  Perk/Item:  Health Upgrade  -  Server - ShopScript (ServerSide):6
  12:13:44.137  Item Cost:  250  -  Server - ShopScript (ServerSide):7
  12:13:44.138  Perk/Item:  Health Upgrade  -  Server - ShopScript (ServerSide):6
  12:13:44.138  Item Cost:  250  -  Server - ShopScript (ServerSide):7
  12:13:44.138  Perk/Item:  Health Upgrade  -  Server - ShopScript (ServerSide):6
  12:13:44.138  Item Cost:  250  -  Server - ShopScript (ServerSide):7
  12:13:44.139  Perk/Item:  Health Upgrade  -  Server - ShopScript (ServerSide):6
  12:13:44.139  Item Cost:  250  -  Server - ShopScript (ServerSide):7
  12:13:44.139  Perk/Item:  Health Upgrade  -  Server - ShopScript (ServerSide):6
  12:13:44.140  Item Cost:  250  -  Server - ShopScript (ServerSide):7
  12:13:44.140  Perk/Item:  Health Upgrade  -  Server - ShopScript (ServerSide):6
  12:13:44.140  Item Cost:  250  -  Server - ShopScript (ServerSide):7

this is just for testing
can u replace

if IsAItemSelectedValue.Value == true and PurchasedItem.Value == false and PressedButtion:GetAttribute("TypeofButtion") == "Item" then
					ButtionCooldown = true
					BuyItemEvent:FireServer(PressedButtion.ItemThatTheButtionsells)
					task.wait(0.2)

with

if IsAItemSelectedValue.Value == true and PurchasedItem.Value == false and PressedButtion:GetAttribute("TypeofButtion") == "Item" then
	ButtionCooldown = true
	print(PurchasedItem.Value)
	if PurchasedItem.Value == false then return end
	BuyItemEvent:FireServer(PressedButtion.ItemThatTheButtionsells)
	task.wait(0.2)

and tell me what it prints

Great doing testing it gave me this error on the server side script

 ServerScriptService.ShopScript (ServerSide):19: attempt to concatenate Instance with nil

Here is the new version of the code

BuyItemEvent.OnServerEvent:Connect(function(Player,Item)
	local CostOfItem = ItemFolder..tostring(Item).Cost
	if Player.leaderstats.BaldiCoins.Value >= CostOfItem.Value then
		Player.leaderstats.BaldiCoins.Value = Player.leaderstats.BaldiCoins.Value - CostOfItem.Value
		Player.PurchasedItem.Value = true
		Player.ItemThatWasPurchased.Value = Item
	end
end)

Line 19 is the local CostOfItem part

1 Like

that error mean that ur trying to compine a string with a nil value its bc of
local CostOfItem = ItemFolder…tostring(Item).Cost
try
local CostOfItem = ItemFolder.tostring(Item).Cost

and u used ItemFolder… idk what … is

simply add 1 dot instead of 2

Its A folder in serverstorage containing all the items

no i mean the 2 dots u did ItemFolder and then . . it should be . only 1 dot