Issus transferring between tables implementing a heart system

the main issue I’m having
the way the heart system is designed is that the hearts are split into ordering and displaying functions, I have both these functions working but the issue is updating the table to its sorted variant for future use (mainly in deleting hearts on damage).

I’ve split it into currenthearts (used for storing the current hearts status) and newtable (the sorted list based on priority), I’ve tried using ‘currenthearts = newtable’ but for some reason this causes the hearts to be deleted two at a time?

I’ve attached all relevant code,
image
image
image
image
image
image

Can you share the code by copying and pasting it?

so it looks like this 

click this button in the forum and then put your code between the code fences.
Screenshot 2023-02-14 at 20.28.39

2 Likes
local currenthearts={{"sour","nul"},{"bitter","nul"},{"umami","nul"},{"minty","nul"},{"savoury","nul"},{"savoury","nul"},{"savoury","nul"},{"spicy","nul"},{"sweet","nul"}}
local counter=1
anim_full=hash("full")
anim_empty=hash("empty")
local heartcounter=56
local hearttable={0}
local deadheart="bruh"
local newtable = {}
local idlist = {}
local sortcounter = 0
local clonecounter =1
local data = {}

--function used to draw the hearts on screen
local function clonehearts(self,garnish,bread)
	self.clone=	gui.new_box_node(vmath.vector3(0,0,0),vmath.vector3(70,65,0))
	table.insert(idlist, self.clone)
	gui.set_texture(self.clone, "heart")
	self.location=gui.set_screen_position(self.clone,vmath.vector3(heartcounter,690,0))
	heartcounter = heartcounter+60
	if garnish == "spicy" then
		gui.play_flipbook(self.clone, "Spicy")
	elseif garnish == "savoury" then
		gui.play_flipbook(self.clone, "Savoury")
	elseif garnish == "sour" then
		gui.play_flipbook(self.clone, "Sour")
	elseif garnish == "sweet" then
		gui.play_flipbook(self.clone, "Sweet")
	elseif garnish == "umami" then
		gui.play_flipbook(self.clone, "Umami")
	elseif garnish == "bitter" then
		gui.play_flipbook(self.clone, "Bitter")
	elseif garnish == "minty" then
		gui.play_flipbook(self.clone, "Minty")
	else
		gui.play_flipbook(self.clone, "full")
	end
end

local function cleardraw(self)
	for i=1,#idlist do
		gui.delete_node(idlist[table.maxn(idlist)])
		idlist[table.maxn(idlist)]=nil
	end
	heartcounter=56
end
--determins the priority of 
local function redraw(self)
	
	newtable={}
	self.priority =0
	while counter < #currenthearts + 1 do
		if  currenthearts[counter][1]=="spicy" then
			self.priority = self.priority + 2
		elseif  currenthearts[counter][1]=="savoury" then
			self.priority = self.priority  + 1.4
		elseif  currenthearts[counter][1]=="sour" then
			self.priority = self.priority  -3
		elseif  currenthearts[counter][1]=="sweet" then
			self.priority = self.priority + 5
		elseif  currenthearts[counter][1]=="umami" then
			self.priority = self.priority + 1
		elseif  currenthearts[counter][1]=="bitter" then
			self.priority = self.priority - 0.1
		elseif  currenthearts[counter][1]=="minty" then
			self.priority = self.priority + 1.2
		end
		data = {currenthearts[counter][1],self.priority}
		if #newtable > 0 then
			while false == false do
				if self.priority <= newtable[sortcounter][2] then
					break
				else
					sortcounter = sortcounter + 1
					if sortcounter > #newtable  then
						break
					end
				end
			end
		end
		table.insert(newtable,sortcounter,data)
		self.priority=0
		sortcounter=0
		counter=counter+1
	end
	counter = 1
	while clonecounter< #newtable + 1 do
		clonehearts(self, newtable[clonecounter][1],newtable[clonecounter][1])
		clonecounter=clonecounter+1
	end
	clonecounter=1
end

function getdamage(self) 
	--ignore this
	local damage = 1
	for i = 1, #newtable do
		if newtable[i][1]=="spicy" then
			damage=damage+1
		elseif newtable[i][1]=="bitter" then
			damage=damage+0.3
		end
	end
	return damage
end

function init(self)
	--ignore this
	msg.post("/player character#pc script","heartsync",{hearts})
	redraw(self)
end

function on_message(self, message_id, message, sender)
	if message_id==hash("damage") then
	--	table.remove(newtable,table.maxn(newtable))
		table.remove(currenthearts,table.maxn(currenthearts))
		cleardraw(self)
		redraw(self)
		--ignore everything past this
		msg.post("/player character#pc script","heartsync",{hearts})
	elseif message_id==hash("death") then
		hearts=10
		counter=0
		heartcounter=56
		hearttable={0}
		gui.set_enabled(gui.get_node("heart1"), true)
		redraw(self)
		msg.post("/player character#pc script","heartsync",{hearts})
	elseif message_id==hash("collectheart") then
	end
end

I haven’t attempted to properly understand your code, but you say you have tried setting currenthearts = newtable. Again - I haven’t looked at your code, but I think there’s a risk that that doesn’t do what you think it does.

currenthearts will become a reference to newtable. It won’t be a copy of newtable at a fixed point in time. Both variables are pointing to the same table in memory. This means that any operations done to newtable (e.g. deleting an entry) will be reflected in currenthearts, and vice versa.

This is how Lua works and it took me some time to properly understand this.

You may want to read these docs from Roblox. It includes example functions to deep copy Lua tables.

In JavaScript, a quick hack is to serialize an object to JSON, then parse it back as an object. Could work in Lua as well if your table doesn’t include functions. Performance would need to be measured of course.

1 Like

Here’s how I deep copy in Defold:

local new_table = sys.deserialize(sys.serialize(old_table))
5 Likes