Why is my copy variable affecting the variable it takes a copy of?

Please let me know if this is the wrong category, however I’m pretty sure this is the right one.

local Recipe = CraftingRecipes[InformationGiven]
local InventoryRecord = Inventories[player.UserId]
warn("inventory",Inventories[player.UserId])
warn("recipe",CraftingRecipes[InformationGiven])
for SlotIDX, Slot in pairs(InventoryRecord[1]) do
	local SlotName, SQuantity = FindSlotNameAndQuantity(Slot)
	local SlotNameFoundIDX = table.find(IngredientNames, SlotName)
	if SlotNameFoundIDX then
		SlotNameFoundIDX += 3
		local IngredientName, IQuantity = FindSlotNameAndQuantity(Recipe[SlotNameFoundIDX])
		warn("ingredient info", IngredientName, IQuantity)
		if SQuantity > IQuantity then
			table.remove(Recipe, SlotNameFoundIDX)
			table.remove(IngredientNames, SlotNameFoundIDX)
		elseif SQuantity < IQuantity then
			Recipe[SlotNameFoundIDX] = tostring(SQuantity - IQuantity)..IngredientName
			InventoryRecord[1][SlotIDX] = "Empty"
		else
			table.remove(Recipe, SlotNameFoundIDX)
			table.remove(IngredientNames, SlotNameFoundIDX)
			InventoryRecord[1][SlotIDX] = "Empty"
		end
	end
end
warn("inventory",Inventories[player.UserId])
warn("recipe",CraftingRecipes[InformationGiven])

Im trying to make a crafting system for my game, which requires me to get copies of a crafting recipe and the players’ inventory (obviously) to see if the player has the items required to make the item. However, the problem is that when I create copies of the original variables, they seem to directly affect the original variable when I interact with the copy later??? what confuses me even more is that the crafting recipe continues to be modified, even when I set it to become readonly earlier in the code???

Original variables (storing the actual copies):

  • Inventories[player.UserId]
  • CraftingRecipes[InformationGiven]

Copy variables (storing copies that I edit to make the calculations):

  • InventoryRecord
  • Recipe

BEFORE ANY CHANGES (FIRST 2 WARNS)
image

AFTER THE CHANGES (LAST 2 WARNS)
image

keep in mind in both of these screenshots these are supposedly the originals, not the copy variables I edit in my code. I am also sure that I am editing the variables I make as copies, and not the main ones, as I have tested by removing any edits to the copies and only then no changes are made.

reason this is happening is becuase the InventoryRecord and Recipe are not copies, but they are the actuall path to the table, so when you use it, it just assumes you are talking about the actual table. What might fix this is:

local Recipe = {CraftingRecipes[InformationGiven]}
local InventoryRecord = {Inventories[player.UserId]}

ohhh, I see what you mean now. However, I tried your solution but it’s still doing the same thing… how would I make it a copy rather than a shortcut??

ooh i know, try:

local Recipe = {unpack(CraftingRecipes[InformationGiven])}
local InventoryRecord = {unpack(Inventories[player.UserId])}

Tell me if that works for you

CLOSE! Recipe variable now works but InventoryRecord is still a shortcut variable…

in lua base types are copied this is number, string, and boolean. All other types are referenced, for you this causes problems with the table type.

Roblox provides a table.clone() function which helps to a degree like so[1]. I think this is what you will need. In your script you will use[2]. I am unsure where IngredientNames is defined but I think much the same.

[2]:

local Recipe = table.clone(CraftingRecipes[InformationGiven])

[1]:

local a = {
    [1] = 200,
    [2] = 450,
    [3] = { 100, 200, 300 },
}

local b = a -- reference
local c = table.clone(a) -- shallow copy

b[1] = 100
c[1] = 999

print(a[1]) -- 100 -our original is changed
print(b[1]) -- 100 -our reference
print(c[1]) -- 999 -our shallow copy/clone

-- but this c[3] is still a reference! we would need a deep-copy for tables in tables
c[3][1] = 999
print(a[3][1]) -- 999

To create a deep-copy of a table try this function.

local function deep_copy(object: {any})
    local copy = {}
    for key, value in pairs(object) do
        if typeof(object) == "table" then
            copy[key] = deep_copy(value)
        else
            copy[key] = value
        end
    end
    return copy
end

sorry for the slow reply, but your function doesnt work; once it meets a string instead of a table it cant run a pairs() loop on it. because of this, i was able to fix it and finally get it and my code to work, like this:

local function deep_copy(object)
	local copy = {}
	if typeof(object) == "table" then
		for key, value in pairs(object) do
			if typeof(object) == "table" then
				copy[key] = deep_copy(value)
			else
				copy[key] = value
			end
		end
		return copy
	else
		return object
	end
end

still, THANK YOU FOR YOUR HELP! without your reply i wouldnt have known what else to do haha

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.