Help with making a halo shop

Hey there,
I am trying to make a halo shop for my game. I can make the UI and halos but Im not sure on how I can keep the halos a player has bought in an inventory that saves and Im not sure how to make the player actually wear the halo.

6 Likes

You will have to use welds for the player to wear the halos and a button to do that.

1 Like

to save any player data, it would be nice to have “Datastore” … I won’t go into this topic, but I use Datastore2,

because you can easily save data and load_

Example:
Datastore2 + Table

--datastore2 stuff
local ServerScriptService = game:GetService("ServerScriptService")
local RS = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

local DataStore2 = require(ServerScriptService:WaitForChild"MainModule")
DataStore2.Combine("DATA", "Halos")

Local PlayerHalos = {
["White Halo"] = false,
["Yellow Halo"] = false,
["Red Halo"] = false,
["Purple Halo"] = false
}

game.Players.PlayerAdded:Connect(function(player) 
local HaloStorage = DataStore2("Halos", player)

local UserHalos = HaloStorage:GetTable(PlayerHalos) 

--You dont need to do something like this: Instance.new("IntValue", player) for example
--The data is stored inside a Table, if you like to see your values, then you can add IntValues



-- Now to actually show in Inventory and LOAD, you will need to do something like this:

--Since Anything related to [GUIS] should be handled in the client then_

--I will make the server send Data to Client:

--Of course, you must create in ReplicatedStorage a Remote Event named: LoadingHalos
--Just for reference, you can name it whatever you want

local SendHalos = game.ReplicatedStorage:WaitForChild("LoadingHalos")

		SendHalos:FireClient(player, UserHalos) --Here will be sent the Table

--For some reason i don't send it directly, i send a Cloned Table instead, because i don't
--know if hackers can mess up with your stuff... (Correct me if this is not correct)

end)

------------------------------------- Local Script --------------------------------------------------------



local RS = game.ReplicatedStorage
local SendHalos = RS:WaitForChild("LoadingHalos")

SendHalos.OnClientEvent:Connect(function(UserHalos) -- Now the Table is on the ClientSide
	
	print"Loading Halos..."
	
local PlayerGui = plr:WaitForChild("PlayerGui")
local PlayerInventory = PlayerGui:WaitForChild("Inventory"):WaitForChild("InventoryBox")
	
--Ok, how i can explain this:
--["Inventory" is the GUI, InventoryBox is a Frame, inside the GUI.
--This will be "where" all
--Player data will load VISUALLY, hackers can mess up with your frames, but the SERVER --knows what the player ACTUALLY has, and what not...
--So it's useless, remember that

--Anyway:

--First: Create a Frame, inside the [Inventory GUI]
--Name it InventoryBox -- Here you will store some other things

--Add Three folders, (Inside InventoryBox ok)
--One called: ItemList 
--Second called: ReserveList 
--Third called: Templates (Warning: Inside this Folder, we will create a new Frame called:
--HaloFrame <<

--Inside HaloFrame, Create these things:
--Some of them are optional... i hope you understand!
--QuantityText > "TextLabel" -- this is to show how many the player has...
--ItemQuantity > "BoolValue" -- this should be false, checks if True of False
--so if you are dealing with "Items that can stack", i suggest chaging to "IntValue" and your "Table" to numbers
--Which Table?, the one we used early, to create and set default values_

--Sell > "IntValue" -- How much the Halo cost?
--StringName > "StringValue" -- this is the name of the Halo, that's why we use a StringValue
--ItemName > "TextLabel" -- this will show the name of the Halo, if the player has one...
--UICorner (Optional)
--UIGradient (Optional)

--ItemImage > "ImageButton" -- when you click on the Item, it will show something


for Halos, HalosValue in pairs(UserHalos) do -- "for i , v in pairs"
	print(Halos, HalosValue) -- if you want to print, do it
	
local FramesToShow = PlayerGui:WaitForChild("Inventory")
			
local NewHaloFrame = FramesToShow.Templates.HaloFrame:Clone() 
--What is this Above?
--[Templates the Folder we created, remember?]
--[HaloFrame is the Frame inside Templates, that will be Cloned]


--The Final Result:
HaloFrame.StringName.Value = Halos -- Shows in the Frame the [Name of the Halo]
HaloFrame.ItemQuantity.Value = HalosValue -- Checking if player has Halo TRUE or False
HaloFrame.QuantityText.Text = HalosValue -- will be FALSE if the player does not have any!
HaloFrame.ItemImage.Image = "rbxassetid://" .. HaloModule[Halos]["Image"]
--Warning: ItemImage.Image will get a image for the Button, if you don't specify, it will not
--show anything, or just a PlaceHolder image from Roblox,
--HaloModule is a Module that i create, i suggest you to learn about Modules, i'm sleeping_

--HaloModule[Halos]["Image"] -- Get the Module, then check for the Name of the Halo, then
--Check for the Image, each Halo is individual

			--if that don't work, try HalosValue -- [Below]
		if Halos == true then -- If the player has some type of HALO, it will show
			HaloFrame.Visible = true -- Showing the Frame
			HaloFrame.Parent = PlayerInventory.ItemList -- Parenting to the ItemList, where anything that is Visible, is Stored...
		else
			ItemFrame.Visible = false
			ItemFrame.Parent = PlayerInventory.ReserveList 
--if the player Halo is False, it will not Show, and it will be sent to ReserveList, so later you can set to True if the player gets one in a near future...				
		end			
	end	
end)

… This works, because i tested (Except the Quantity.Text with True or false values, i think it may do some error… if that happens just change to 1 the Text, if something does not work, then probaly you missed some value or something

8 Likes

Oh wow, you didnt have to write all that :flushed: but using that script would you be able to grant people halos in other scripts. For example if a players was #1 on a leaderboard and I wanted to give them a halo as a prize would that be possible?

Yes, and you don’t even need other [Scripts] — that could be made in one script_
but, Yes, you can, but you would need to call the Datastore2 in that Script-
for example:

Script1 = [Created all PlayerData and stuff]
Script2 = [Leaderboard stuff, if the player is in Rank 1st, then he will be awarded a Exclusive Halo]

That’s why datastore is usefull, you can easily interact with values as you wish

Now if you have alot of functions ( like this )

game.Players.PlayerAdded:Connect(function(player) 
local HaloStorage = DataStore2("Halos", player)

local UserHalos = HaloStorage:GetTable(PlayerHalos) 

PickedItem.OnServerEvent:Connect(function(player, item)
local HaloStorage = DataStore2("Halos", player)

local UserHalos = HaloStorage:GetTable(PlayerHalos) 

if item == UserHalos["White Halo"] then -- this is an example that i randomly wrote
-- this is just an example, you need to specify the Datastore2
(Which value the player is updating?) -- think like this

end

For each function you would need to ‘‘Call’’ Datastore2 specific value again_

Now, to create a Leaderboard for Rankings, that’s another p-p topic, but it’s possible

2 Likes

Oh thank you so much! I do already have a global leaderboard so don’t worry about that. And I will get to making that halo shop you provided above in a second. Also would you happen to know anything about chat tags? Like when in the chat its says something like “[Owner]:” next to their name?

Yes, i did something like this:

["Warning"] you must edit some things in the BillboardGui to suit Size and some other Details, there is a video on Youtube that explain really well just in case

Create a BillboardGui in [ServerStorage] -- so hackers will not mess with it i guess_
Inside BillBoardGui - Create Two "TextLabel"
--Name it >>  NameTag
LowerText
UpperText

---------------Server Script --------------
local ServerStorage = game:GetService("ServerStorage")
local Tag = ServerStorage.NameTag

game.Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(char)
		local Head = char.Head
		local newtext = Tag:Clone() 
		local uppertext = newtext.UpperText
		local lowertext = newtext.LowerText
		
		
		newtext.Parent = Head
		newtext.Adornee = Head
		uppertext.Text = player.Name
		
		if player.Name == "JackFr_ost" then -- Your name
			uppertext.TextColor3 = Color3.fromRGB(221, 255, 202)
			lowertext.Text = "Your Title Here"
			lowertext.TextColor3 = Color3.fromRGB(202, 104, 18)
		elseif player.Name == "Some Friend" then
			lowertext.Text = "Cool"
			lowertext.TextColor3 = Color3.fromRGB(138, 234, 255)
		elseif player.Name == "Another Friend" then
			lowertext.Text = "Legendary Halo User"
			lowertext.TextColor3 = Color3.fromRGB(136, 89, 190)
				
		end
		
	end)
end)



1 Like

Thank you so much your amazing!

1 Like

Im so sorry to annoy you again but I have this leaderboard script here right. It works great I just want to change a value inside the player so that way I can make a chat tag if the player is on the leaderboard like “[#1 player]:” but im not sure where to put and update the variable inside the player/

local dataStoreService = game:GetService("DataStoreService")
local dataStore = dataStoreService:GetOrderedDataStore("GlobalLeaderboard")

local currencyName = "Wins" -- Your currency name

tp.Value.Text = currencyName

wait(10)

while true do
	for i, plr in pairs(game.Players:GetChildren()) do
		if plr.UserId > 0 then
			local w = plr.leaderstats[currencyName].Value 
			if w then
				pcall(function()
					dataStore:UpdateAsync(plr.UserId,function(oldVal)
						return tonumber(w)
					end)
				end)
			end
		end
	end
	local smallestFirst = false -- False = 2 before 1, true = 1 before 2
	local numberToShow = 10 -- How many ranks the leaderboard will have, between 1-100
	local minValue = 1 -- If the player has a lower currency value than this, the player will not be shown in the leaderboard
	local maxValue = 10e30 -- If the player has a higher currency value than this, the player will not be shown in the leaderboard
    local pages = dataStore:GetSortedAsync(smallestFirst, numberToShow, minValue, maxValue)
    local top = pages:GetCurrentPage()
	local data = {}
	for a,b in ipairs(top) do
		local userid = b.key
		local points = b.value
		local username = "[Failed To Load]"
		local s,e = pcall(function()
		 username = game.Players:GetNameFromUserIdAsync(userid)
		end)
		if not s then
		   warn("Error getting name for "..userid..". Error: "..e)
		end
		table.insert(data,{username, points, userid})
	end
	ui.Parent = script
	sf:ClearAllChildren()
	ui.Parent = sf
	for number,d in pairs(data) do
		local name = d[1]
		local val = d[2]
		local id = d[3]
		local color = Color3.new(255, 255, 255)
		local event = game.ReplicatedStorage.Events.ChatTag
		if number == 1 then
			color = Color3.new(255, 255, 0)
			for _, v in pairs(script:GetDescendants()) do
				if v:IsA("Humanoid") and v.Name == "Humanoid" then
					local playerDescription = game:GetService("Players"):GetHumanoidDescriptionFromUserId(id)
					v:ApplyDescription(playerDescription)
					v.Parent.Name = name
				end
			end
		elseif number == 2 then
			color = Color3.new(204, 204, 204)
		elseif number == 3 then
			color = Color3.fromRGB(170, 85, 0)
		elseif  number <= 25 then
			print("top #" .. number)
		end
		local new = sample:Clone()
		new.Name = name
		new.LayoutOrder = number
		new.Place.Text = number
		new.Place.TextColor3 = color
		new.PName.Text = name
		new.Value.Text = val
		new.Parent = sf
	end
	wait()
	sf.CanvasSize = UDim2.new(0,0,0,ui.AbsoluteContentSize.Y)
	wait(10)
end
1 Like

i would like to help, but since i gtg… this post might be useful i think: How would I make chat tags?

1 Like

Thats alright tysm, and for when you get back where should I put the local script for the halo shop.

xD for example
[StarterGui Area]
I have a Shop “Gui”, and inside this Gui i have a [Local script] >> [ that has Shop functions ]

I put them inside the Gui that I’m going to use-- it makes more sense to me

But a extra quote:
"Local scripts should be placed in StarterPlayerScripts, if they are made for something that has to do with character or humanoid of the player, place it in StarterCharacterScripts. If the script is for loading screens, or anything to do with while the game has not loaded, place it in ReplicatedFirst.

1 Like

Oh alright that makes sense tysm, also do u have a reference photo of the halo shop u made? cus I’m not exactly sure what the end goal I’m working towards is. Thank you so much for all your help tho

Create a Part in your Workspace,
Name it “ShopButton”
Insert a [ClickDetector]

For a Shop gui, just create something like a shop, it can be anything (The design)

How i did my Shop Gui:

Created a Gui — Called: ShopGui
Inside ShopGui, insert a [Frame] – Called: ShopInterface
Inside ShopGui, insert a [Frame] – Called: ShopDecoration (Some extra frame to create a border for example

Inside ShopGui, Insert a [ImageLabel] – Called: ItemShow ( Will be to show the Image of the Item)
–Inside ItemShow, insert (Optional ) a “Frame” – so you can make a border (Decoration) for it…
–Inside ItemShow, Insert a “TextButton” – Called: Buy – will be used very soon
–Inside ItemShow, Insert a “TextButton” – Called: Verify – This may be something to “Try out” the Halo or something else, you can add alot of buttons for different functions

–Inside Buy Button, Insert a “StringValue” – Called: ItemName – Important [ So you can create alot of Frames

-------------------------------------------------- { Server Script to Show Shop Gui } -------------------------------

local ShopGui = game.StarterGui.Shop

game.workspace.ShopButton.ClickDetector.MouseClick:Connect(function(player) 

   if ShopGui.Enabled == true then
       ShopGui.Enabled = false -- Disable the Gui if the button is clicked Twice
else if ShopGui.Enabled == false then
      ShopGui.Enabled = true -- Enable and Show the Gui [Only if the Gui is Not visibile for example
       end
	
	
	--This is only to Show the Gui [ And Disable it ]
end)

------------------------------------------------------------------[Local Script]

local player = game.Players.LocalPlayer

local RS = game.ReplicatedStorage
local ChoosedItem = RS:WaitForChild("PurchaseConfirmation")

script.Parent.MouseButton1Click:Connect(function(player) --When we click this button, we will buy the item that is Shown for example
	
	
local ItemName = script.Parent.ItemName.Value -- The item was referenced here, so when the player CLICK, this will happen
	
	
ChoosedItem:FireServer(player, ItemName) -- See, the value will be passed to the Server, So the hacker cannot exploit any stuff-

He can, in fact, pass any false argument or something else, 
but the server will be like this:

--So? the player just sent to me a Legendary Halo...Indeed, BUT! -  he doens't have enough money, so.. [No]
--The player distance is too far from the shop? what he is trying to do [Kick player]
--If the exploit change the Name of the ItemName argument, it will be nothing, because the server
has knowledge to manipulate all types of values_

The server knows that White Halo cost 50, and Legendary Halo cost 200, for example...
So there is no way to bypass this ( Only if you get a backdoor ( virus scripts )
	
end)

----------------------------------------------------------------- (Server Script)

PlayerPurchased.OnServerEvent:Connect(function(player, ItemName) -- The item is on the server, but what is the Name of it? we gonna check_
	
	
	local UserHalosStorage = DataStore2("Halos", player)
	
	
	local UserHalos = UserHalosStorage:GetTable(UserHalos) -- Will get the Halos of the player
	--just for a short example:
	
	
	if ItemName == "White Halo" then 	--Check if the ItemName is Equal to the Specified Halo we designed here
		
		if player.Money.Value >= 50 then -- THIS IS a random currenty that i added, so if the player does not have enough money, it will NOT WORK 
		
		print"The Player want to buy White Halo"
	else
		print"Not enough Money to afford that..."
	end
		
		
	else if ItemName == "Yellow Halo" then --Same thing, but will check for Yellow Halo
			
			
		end
	end 
	
	
	-- if you don't want to use alot of Else ifs, then you can do what i did Below
	
	
	
	
	
	
	
	
	
	-- THIS IS used for any type of item, you only need to change a few things to your like --
	
	
	local VerifiedItems = game.ServerStorage.VerifiedFolder -- This is where all String Values are storaged [Just for Reference]
	
	local ValidItem = VerifiedItems:FindFirstChild(ItemName) -- Will search for the First Thing named: "ItemName" >> "White Halo"
	--if somehow the String is not inside the Folder, it will not work, and may thrown an error, because the ItemName does not exist...
	
	if ValidItem == ItemName then -- If we found something Equal to the name of [The item that we want to Purchase] Then it will work
		print(ItemName .. "Is a Verified and Valid item, Proceed")
		
		if player.Money.Value >=HalosModule["PriceList"][ItemName] then -- This is a module to make things easy (Money is Highter than or Equal to the Halo Price)

--The module may look like this

			["PriceList"] = {
				
				["White Halo"] = 50,
				["Yellow Halo"] = 100,
				["Red Halo"] = 150
				--Etc
			}


	--First, it will Enter the ["PriceList"] ... 

	--Second, it will check the ItemName, Aka: White Halo, for example
			
			UserHalos[ItemName] = true -- UserHalos is the Halos Table /// [ItemName] is the Item that will be referenced! (The name of the Item)
			
			--Will set to True inside the Table for the current Halo that the player Bought, after that we need to save their data
			
			--I save like this for example:

			UserHalosStorage:Set(UserHalos)
			--Set will update all values inside the table, saving all
		end
	end	
end)

this was just an example, but you can do whatever you want :label:

1 Like

Sorry for replying so late, I was sleeping. Thank you so much tho :))

Question, Is there 2 different guis for the shop and inventory

well I tried making it but its really just so confusing.

(Sorry for the late reply)

Here how it looks like:

Explorer:

How

Except Upgrades (The Value) , this is for something else, the rest is everything you need…
And ItemType is not necessary too

ItemType and ItemName are “StringValues” so you can put anything to Sell from the shop here
(The values Below ItemShowDecoration) are not necessary

you Only need the values that are inside “Buy” Button

I made a bit different from what i wrote here but it has the same essence, so everything 100% works if you put at the right references