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.
You will have to use welds for the player to wear the halos and a button to do that.
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
Oh wow, you didnt have to write all that 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
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)
Thank you so much your amazing!
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
i would like to help, but since i gtgā¦ this post might be useful i think: How would I make chat tags?
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.
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
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:
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