I’d like the items to be randomized based on their Rarity.Value (NumberValue) (1 being most common to 4 being extremely rare) instead of just selecting random items from the Shop folder in ReplicatedStorage.
What is the issue?
Currently, the script just selects a random item within the Shop folder without checking it’s Rarity.Value
What solutions have you tried so far?
I’ve tried re-rewriting my script many many time but I’m back at square one…
ServerScript that randomizes the items (in ServerScriptService)
local replicatedStorage = game:GetService("ReplicatedStorage")
local shopFolder = replicatedStorage:WaitForChild("Shop")
local workspace = game:GetService("Workspace")
-- Find all the SpecialDisplay1 objects in the workspace
local specialDisplays = workspace:GetDescendants()
for _, obj in ipairs(specialDisplays) do
if obj.Name == "SpecialDisplay" then
-- Find all the ObjectDisplay children of each SpecialDisplay1 object
local objectDisplays = obj:GetDescendants()
for _, child in ipairs(objectDisplays) do
if child.Name == "ObjectDisplay" then
-- Spawn a random model for each ObjectDisplay child
local function spawnRandomModel()
local models = shopFolder:GetChildren()
if #models == 0 then
print("There are no models in the shop folder.")
return
end
local randomModelIndex = math.random(1, #models)
local randomModel = models[randomModelIndex]
local clonedModel = randomModel:Clone()
-- Find the root part of the cloned model
local rootPart = clonedModel.PrimaryPart.CFrame.Position
-- Calculate the offset between the root part and the ObjectDisplay child
local offset = child.Position - rootPart
-- Parent the cloned model to the ObjectDisplay child and move it to the correct position
clonedModel.Parent = child
clonedModel:SetPrimaryPartCFrame(CFrame.new(child.Position)) --+ offset))
end
-- Spawn a random model immediately for each ObjectDisplay child
spawnRandomModel()
-- Spawn a new random model for each ObjectDisplay child every 30 minutes
--while true do
-- wait(30 * 60)
-- spawnRandomModel()
-- end
end
end
end
end
ClientScript within the GUI that finds the model within the ObjectDisplay part and makes it correspond to the purchase GUI
-- Get the ObjectDisplay part from the SpecialDisplay1 in the workspace that has Num.Value == 1
local objDisplay
for _, specialDisplay in ipairs(game.Workspace:GetDescendants()) do
if specialDisplay.Name == "SpecialDisplay" then --specialDisplay:IsA("Folder") and
local numValue = specialDisplay:FindFirstChild("Num")
if numValue and numValue:IsA("NumberValue") and numValue.Value == 1 then
objDisplay = specialDisplay:FindFirstChild("ObjectDisplay")
break
end
end
end
--if objDisplay.Parent.Num.Value == 1 then
-- correctstand = true
--end
-- Loop through each slot in the grid
for i, slot in ipairs(script.Parent.Slots:GetChildren()) do
-- Check if the slot is a Frame object
if slot:IsA("Frame") then
-- Add a MouseEnter event listener to the slot
slot.MouseEnter:Connect(function()
-- Clone the first child and set its parent to the ViewportFrame.Model property of the specific slot
local firstChild = objDisplay:GetChildren()[1]
print(firstChild) -- check the value of firstChild
-- Get the first child of the ObjectDisplay part and set the ItemName object in the Info variable to its Name property
Info.ItemName.Text = firstChild.Name
Info.ItemDescription.Text = firstChild:FindFirstChild("Desc").Value
script.Parent.Slots.Cost.Text = "Coins: ".. firstChild:FindFirstChild("Cost").Value --added
-- Clone the first child and set its parent to the ViewportFrame.Model property of the specific slot
local clonedChild = objDisplay:GetChildren()[1]:Clone()
clonedChild.Parent = slot.ViewportFrame.Model
-- Set the Visible property of the Info object to true
Info.Visible = true
end)
-- Add a MouseLeave event listener to the slot
slot.MouseLeave:Connect(function()
-- Set the Visible property of the Info object to false
Info.Visible = false
end)
local slotframe = script.Parent.Slots
local function update(specific)
-- Disable and re-enable the RotateVis script under the specific slot's parent
local rotateVis = slotframe:FindFirstChild(specific).RotateVis
rotateVis.Disabled = true
rotateVis.Disabled = false
end
--update()
local slots = script.Parent.Slots
--// glowing selection reset
slots.Primary.ImageButton.Transparency =1
local equipped = true
for i, slot in ipairs(script.Parent.Slots:GetChildren()) do
-- Check if the slot is a Frame object
if slot:IsA("Frame") then
-- Add a MouseClick event listener to the slot
slot.ImageButton.MouseButton1Click:Connect(function(player)
-- Get the first child of the ViewportFrame.Model and set the itemName variable to its Name property
local itemModel = slot.ViewportFrame.Model:GetChildren()[1]
local itemName = itemModel.Name
local player = game.Players.LocalPlayer
print(player) -- This will print the value of player in the console
print(player.leaderstats)
-- Check if the slot has an item equipped
local shopitem = objDisplay:GetChildren()[1]
local itemcost = shopitem:FindFirstChild("Cost").Value
if equipped == true and itemcost > player.leaderstats:FindFirstChild("Coins").Value then
player.PlayerGui.GameInventory.DeleteOneMsg.Visible = true
player.PlayerGui.GameInventory.DeleteOneMsg.Msg.Text = "You don't have enough coins."
--player.PlayerGui.GameInventory.Frame.Visible = true
wait(2)
player.PlayerGui.GameInventory.DeleteOneMsg.Visible = false
else
if equipped == true and itemcost <= player.leaderstats:FindFirstChild("Coins").Value then
local event = game.ReplicatedStorage.InvEvents.PickUp
local purchaseitem = game.ReplicatedStorage.ShopEvents.Purchase
local item = itemName
local firstChild = itemModel
local itemdescription = firstChild:FindFirstChild("Desc").Value
event:FireServer(item, itemdescription)
purchaseitem:FireServer(itemcost)
-- Set the Equipped value of the item to false and hide the item in the slot
equipped = false
slot.Visible = false
-- Clear the model of the slot to remove the item from the slot
slot.ViewportFrame.Model:ClearAllChildren()
-- Update the value in the settings for the slot
if slot == slotframe.Primary then
script.Parent.Settings.Primary.Value = ''
end
end
-- Play a sound
playSound()
-- script.Parent.Slots.Visible = false
script.Parent.Parent.Parent:Destroy()
end
end)
end
end
end
end
Ignore the - - ed out lines, that’s from me trying to figure things out
I assigned a Rarity.Value to the objects using a NumberValue object within each model named “Rarity”. I’m still a bit new to scripting so I’m not really sure how to go about creating a table
local replicatedStorage = game:GetService("ReplicatedStorage")
local shopFolder = replicatedStorage:WaitForChild("Shop")
local workspace = game:GetService("Workspace")
-- Define the items and their rarities
local Items = {
Crate = 1,
Stealth = 3,
["Loot Finder"] = 4,
}
-- Find all the SpecialDisplay1 objects in the workspace
local specialDisplays = workspace:GetDescendants()
for _, obj in ipairs(specialDisplays) do
if obj.Name == "SpecialDisplay" then
-- Find all the ObjectDisplay children of each SpecialDisplay1 object
local objectDisplays = obj:GetDescendants()
for _, child in ipairs(objectDisplays) do
if child.Name == "ObjectDisplay" then
-- Spawn a random model for each ObjectDisplay child
local function spawnRandomModel()
local models = {}
for name, rarity in pairs(Items) do
if rarity >= math.random(1, 4) then
local model = shopFolder:FindFirstChild(name)
if model then
table.insert(models, model)
end
end
end
if #models == 0 then
print("There are no models in the shop folder with the required rarity.")
return
end
local randomModelIndex = math.random(1, #models)
local randomModel = models[randomModelIndex]
local clonedModel = randomModel:Clone()
-- Find the root part of the cloned model
local rootPart = clonedModel.PrimaryPart.CFrame.Position
-- Calculate the offset between the root part and the ObjectDisplay child
local offset = child.Position - rootPart
-- Parent the cloned model to the ObjectDisplay child and move it to the correct position
clonedModel.Parent = child
clonedModel:SetPrimaryPartCFrame(CFrame.new(child.Position)) --+ offset))
end
-- Spawn a random model immediately for each ObjectDisplay child
spawnRandomModel()
-- Spawn a new random model for each ObjectDisplay child every 30 minutes
--while true do
-- wait(30 * 60)
-- spawnRandomModel()
-- end
end
end
end
end
It doesn’t do anything with the rarity of the object, instead, it’s getting the number of objects you have in total for example lets say you have 10 models, it’s going to be a 1/10 chance for everything
local replicatedStorage = game:GetService("ReplicatedStorage")
local shopFolder = replicatedStorage:WaitForChild("Shop")
local workspace = game:GetService("Workspace")
-- Define the items and their rarities
local Items = {
Crate = 1,
["Beast Sense II"] = 3,
["Soul Seeker III"] = 4,
}
-- Split the items into separate lists based on rarity
local commonItems = {}
local uncommonItems = {}
local rareItems = {}
local ultraRareItems = {}
for item, rarity in pairs(Items) do
if rarity == 1 then
table.insert(commonItems, item)
elseif rarity == 2 then
table.insert(uncommonItems, item)
elseif rarity == 3 then
table.insert(rareItems, item)
elseif rarity == 4 then
table.insert(ultraRareItems, item)
end
end
-- Find all the SpecialDisplay1 objects in the workspace
local specialDisplays = workspace:GetDescendants()
for _, obj in ipairs(specialDisplays) do
if obj.Name == "SpecialDisplay" then
-- Find all the ObjectDisplay children of each SpecialDisplay1 object
local objectDisplays = obj:GetDescendants()
for _, child in ipairs(objectDisplays) do
if child.Name == "ObjectDisplay" then
-- Spawn a random model for each ObjectDisplay child
local function spawnRandomModel()
-- Select a random rarity level first
local rarityLevel = math.random(1, 4)
-- Select a random item from the list of items for the selected rarity level
local itemsList = commonItems
if rarityLevel == 2 then
itemsList = uncommonItems
elseif rarityLevel == 3 then
itemsList = rareItems
elseif rarityLevel == 4 then
itemsList = ultraRareItems
end
local numItems = #itemsList
if numItems == 0 then
print("There are no items with rarity level "..rarityLevel..".")
return
end
local randomItemIndex = math.random(1, numItems)
local randomItemName = itemsList[randomItemIndex]
local randomModel = shopFolder:FindFirstChild(randomItemName)
if randomModel == nil then
print("Model not found for item "..randomItemName..".")
return
end
local clonedModel = randomModel:Clone()
-- Find the root part of the cloned model
local rootPart = clonedModel.PrimaryPart.CFrame.Position
-- Calculate the offset between the root part and the ObjectDisplay child
local offset = child.Position - rootPart
-- Parent the cloned model to the ObjectDisplay child and move it to the correct position
clonedModel.Parent = child
clonedModel:SetPrimaryPartCFrame(CFrame.new(child.Position)) --+ offset))
end
-- Spawn a random model immediately for each ObjectDisplay child
spawnRandomModel()
-- Spawn a new random model for each ObjectDisplay child every 30 minutes
--while true do
-- wait(30 * 60)
-- spawnRandomModel()
-- end
end
end
end
end
Does this seem to be a better way of using math.random?
I won’t go through the entire function but it’s best practice to have your rarities add up to 100(%) so it’s easier to control exactly how “rare” something should be…
local Items = {
Crate = 66,
Stealth = 33,
["Loot Finder"] = 1,
}
local Seed = Random.new(tick())
local function PickItem(RarityList: {[string]: number}): string
local Num = Seed:NextNumber(0, 100)
local Int = 0
for Item, Chance in pairs(Items) do
Int += Chance
if Num <= Int then
return Item
end
end
end
local ChosenItem = PickItem(Items)
print(ChosenItem) -- 66% chance to be Crate, 33% chance to be Stealth, 1% chance to be Loot Finder
Thank you!!! This was extremely helpful; however, I’m struggling to figure out how to implement what you’ve given to me within the script I currently have written?
local replicatedStorage = game:GetService("ReplicatedStorage")
local shopFolder = replicatedStorage:WaitForChild("Shop")
local workspace = game:GetService("Workspace")
-- Define the items and their rarities
local Items = {
Crate = 30,
["Beast Sense I"] = 15,
["Soul Seeker I"] = 15,
["Loot Finder I"] = 20,
["Stealth I"] = 20,
["Beast Sense II"] = 10,
["Soul Seeker II"] = 10,
["Loot Finder II"] = 10,
["Stealth II"] = 10,
["Soul Seeker III"] = 5,
["Loot Finder III"] = 5,
["Beast Sense III"] = 5,
["Stealth III"] = 5,
}
-- Find all the SpecialDisplay1 objects in the workspace
local specialDisplays = workspace:GetDescendants()
for _, obj in ipairs(specialDisplays) do
if obj.Name == "SpecialDisplay" then
-- Find all the ObjectDisplay children of each SpecialDisplay1 object
local objectDisplays = obj:GetDescendants()
for _, child in ipairs(objectDisplays) do
if child.Name == "ObjectDisplay" then
-- Spawn a random model for each ObjectDisplay child
local Seed = Random.new(tick())
local function PickItem(RarityList: {[string]: number}): string
local Num = Seed:NextNumber(0, 100)
local Int = 0
for Item, Chance in pairs(Items) do
Int += Chance
if Num <= Int then
return Item
end
end
end
local ChosenItem = PickItem(Items)
print(ChosenItem) -- 66% chance to be Crate, 33% chance to be Stealth, 1% chance to be Loot Finder
local clonedModel = ChosenItem:Clone()
-- Find the root part of the cloned model
local rootPart = clonedModel.PrimaryPart.CFrame.Position
-- Calculate the offset between the root part and the ObjectDisplay child
local offset = child.Position - rootPart
-- Parent the cloned model to the ObjectDisplay child and move it to the correct position
clonedModel.Parent = child
clonedModel:SetPrimaryPartCFrame(CFrame.new(child.Position)) --+ offset))
end
-- Spawn a random model immediately for each ObjectDisplay child
--PickItem()
-- Spawn a new random model for each ObjectDisplay child every 30 minutes
--while true do
-- wait(30 * 60)
-- spawnRandomModel()
-- end
--end
end
end
end