Help -- Getting variables from tables and communicating them into the game physically

Hey everyone, I have a script that runs a randomizer, that finds the ‘rarity’, and the ‘item’ from 3 different tables (uncommon, common, and their ‘items’.

I’m wondering how I could take these variables (itemRarity, chosenItem), and ‘convert’ them into an object in the game through ReplicatedStorage. I have folder(s) in RepStorage of the Common & Uncommon ‘tables’ of items, but I don’t know how to communicate that into the script to actually create/clone the modles I’m looking for. If anyone has any ideas please let me know!

Images – The script

local rarities = {
	"Common",
	"Uncommon",
}
local itemCommon = {
	"Tin Can",
	"Plastic Bag",
	"Water Bottle"
}
local itemUncommon = {
	"Glass Bottle",
}

local itemRarity = ""
local chosenItem = ""

local function newItem()
	local commonR = "Common"
	local uncommonR = "Uncommon"
	local rarityChance = 0

	
	rarityChance = math.random(1,100)
	print(rarityChance)
	
	if rarityChance < 75 then 
		itemRarity = "Common"
		chosenItem = math.random(1, #itemCommon)
	else
		itemRarity = "Uncommon"
		chosenItem = math.random(1, #itemUncommon)
	end
end

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local SandyS = ReplicatedStorage.SandyShallows:GetChildren("BoolValue")

local folder = ReplicatedStorage.SandyShallows

for _, v in ipairs(folder:GetChildren()) do --loop through the folder
	if v.Value == false then
		newItem()
		print(v.Name, chosenItem, itemRarity)
		v.Value = true
	end
	print(v.Name, v.Value)
end
1 Like

All you have to do is use the string stored in ‘chosenItem’ to find the item in your folders.

Here’s how you can do that:

for _, v in ipairs(folder:GetChildren()) do --loop through the folder
	if v.Value == false then
		newItem()
		print(v.Name, chosenItem, itemRarity)

        local itemModel = yourFolderReference:FindFirstChild(chosenItem):Clone() -- obviously replace 'yourFolderReference' with the actual reference to ur folder
        itemModel.Parent = game.Workspace -- (or wherever u need it)

		v.Value = true
	end
	print(v.Name, v.Value)
end

I’ll be honest with you though, your code has a lot of flaws and inefficiency in just about every part of it so if this script needs to be scaled later down the line, let me know and I’ll rewrite the whole thing for you.

Oh okay, I didn’t know it was that easy.

As you may have been able to tell I am fairly new to scripting so if you want to run down the optimization or just make a whole new, better script you can do that as well.

Thanks!

Yeah! So i was kinda bored so i actually did decide to optimize your script for you.

The first thing I did was rework how your tables were structured. Instead of being flat tables, they are now dictionaries which are more organized and easier to work with in this use case. Doing it this way also makes it easily expandable if you want to add more rarities and items in the future.

I added a utility function for getting a random item in a weighted table (assuming the function is provided one; which it must be)

I also reworked your ‘newItem()’ function so that it uses a return statement, that way no outer variables are required. It is also neater/optimized.

Your for loop I mostly left the same and just added the model cloning statements.

--//Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--//References
local folder = ReplicatedStorage.SandyShallows
local yourReferenceFolder = ReplicatedStorage.SomeItemFolder -- change to your folder reference

--//Variables
local rarities: {} = {
	["Common"] = 75,
	["Uncommon"] = 25
}

local items: {} = {
	["Common"] = {
		"Tin Can",
		"Plastic Bag",
		"Water Bottle"
	},
	
	["Uncommon"] = {
		"Glass Bottle"
	}
}

--//Functions

--[[
	Don't even worry about how this works. 
	Just know it's a recursive function that will return a random element from a weight table.
	A weight table should look something like this btw:
	
	local chances = {
		Common = 50,
		Rare = 20,
		Legendary = 1
	}
	
	@returns {string}
]]
local function _weightedChance(t, _a, _b): string
	return
		_a
		and (_a > 0
			and -math.random(1, _a)
			or _a < 0
			and (select(2, next(t, _b)) >= -_a
				and next(t, _b)
				or _weightedChance(t, _a + select(2, next(t, _b)), next(t, _b)))
			or (next(t, _b)
				and select(2, next(t, _b)) + _weightedChance(t, 0, next(t, _b))
				or 0))
		or _weightedChance(t, _weightedChance(t, _weightedChance(t, 0)))
end

--[[
	A function that returns the name of a random item as well as the rarity it falls under.
	
	@returns {string, string | nil, nil}
]]
local function newItem(): string | nil
	local rarity: string = _weightedChance(rarities)
	local randomIndex: number = math.random(1, #items[rarity])
	local chosenItem: string = items[rarity][randomIndex]
	
	return chosenItem, rarity
end

--//Loops
for _, val in ipairs(folder:GetChildren()) do -- I'm going to mostly leave this untouched bc idk what the bool value and whatnot is in reference to
	if val.Value == false then
		local item: string, rarity: string = newItem()
		local itemModel = yourReferenceFolder:FindFirstChild(item)
		
		local clonedItem = itemModel:Clone()
		clonedItem.Parent = game.Workspace
		
		print(val.Name, item, rarity)
		val.Value = true
	end
	
	print(val.Name, val.Value)
end

That is all though. If it doesn’t work or you have questions let me know.

Also I should mention, the weightedChance function was made by @loleris so credit goes to him for that

1 Like

Hey, so all I did was paste the script into RepStorage, and it displayed 2 warnings:
Line 72;


Line 49;

Did you copy the script I gave you exactly? Nothing more and nothing less?
And did you change the reference folder variable to your specific folder?

Because it still works perfectly fine for me, I’m not getting warnings.

Hey not sure if this helps, but here’s how I make my Randomizers.

function(chances: {}, luck: number)
	
	local luck = luck or 1
	local chances = table.clone(chances)
	
	--Lets get total chance
	local totalChance: number = 0

	for _, chance in ipairs(chances) do
		totalChance += chance
	end

	--Lets apply luck
	for i, chance in ipairs(chances) do
		if chance / totalChance <= .1 then
			chances[i] *= luck
		end
	end

	--Lets scale chances into relative weights
	local n: number = 0
	local totalWeight: number = 0
	local options = {}
	local relativeWeights = {}

	--Lets get total weight and seperate options and relative weights
	for option, relativeWeight in ipairs(chances) do
		n += 1
		totalWeight += relativeWeight

		options[n] = option
		relativeWeights[n] = relativeWeight
	end

	--Time calculate relative weights
	for i = 1, n do
		relativeWeights[i] /= totalWeight
	end

	--Time to choose
	local choosenNum: number = randomizer:NextNumber()

	for i = 1, n do
		choosenNum -= relativeWeights[i]

		if choosenNum < 0 then
			return options[i]
		end
	end
end
function module.getRandomPet(player : Player, pets : {})
	--Time to format pets table, it will help us rarity such as same for example if we have two 35 rarity we make them one so it makes it equal 
	--since those both pets has same chances
	local chances = {}

	for i, pet in ipairs(pets) do
		chances[i] = pet.Rarity
	end

	--Luck
	local ownsLucky = MarketPlaceService:UserOwnsGamePassAsync(player.UserId,GameSettings.PassesId.Lucky) or player:WaitForChild("Passes"):FindFirstChild('Lucky') or player:WaitForChild("Boosts"):FindFirstChild('Lucky')
	local ownsSuperLucky = false

	local luck = 1.25 --starts with 25% luck

	if ownsLucky == true then --50% better luck
		luck += .5
	end

	if ownsSuperLucky == true then -- 100% better luck
		luck += 1
	end

	if player:GetAttribute('VIP') == true then -- 15% better luck for vip
		luck += .15
	end

	local roll = module.ChanceRoll(chances, luck)
	local choosenPet = pets[roll].PetId

	return choosenPet
end

How do I have the Pets Saved?

['Pets'] = {
			[1] = {PetId = 'Noob', Rarity = 50},
			[2] = {PetId = 'Fox', Rarity = 35},
			[3] = {PetId = 'Monkey', Rarity = 14},
			[4] = {PetId = 'Flamingo', Rarity = 0.99},
			[5] = {PetId = 'Parrot', Rarity = 0.01},
			[6] = {PetId = 'Dragon', Rarity = 0.001},
		}
1 Like