Nil value returned when calling a field (SOLVED)

	timer.delay(3, false, function (self, handle, time_elapsed)
		print("hello")
		self.enemy_damage = false
	end)

In the code above it should print hello and change the varialbe self.enemy_damage to true after 3 seconds. But when executed it returns:
image

for context: the timer.delay function is on line 145 and it is called by a line of code at line 159

I know that if a nil value is returned it means that i have put the wrong thing into the timer.delay function like a string instead of a intager. I’ve messed around with it for a while by changing the delay which in the code snippet is 3 to 3.0, and “three” but i got the same error. I also tried assigning the function as a variable but it didn’t seem to change anything. I’ve read the documentation API reference (timer) but couldn’t find anything to help me source the error. Do i need to import anthing or write any code before the timer.delay function can operate?

Also many thanks to Mathias_Westerdahl for helping me navigate setting the function up

Can you show all of the code in that script please?

I ask because it looks like you have somehow replaced timer.delay with nil. If you put that code in an empty script it works. If you modify it to this:

timer.delay = nil
timer.delay(3, false, function (self, handle, time_elapsed)
		print("hello")
		self.enemy_damage = false
	end)

Then you get the error you are seeing.

this is the rest of the code in the function local function

local function player_damage(self, normal, distance)
	self.enemy_contact = true
	msg.post("player#player_hit", "play_sound")
	msg.post("/health#health", "remove_life")
	
	timer.delay(3, false, function (self, handle, time_elapsed)
		print("hello")
		self.enemy_contact = false
	end)
end

this is the function that calls it:

function on_message(self, message_id, message, sender)
	if message_id == msg_contact_point_response then --this subroutine will run if a contact point message has been made
		if message.group == group_obstacle then --this will cause line 110 to run if the contact point is an obstacle
			handle_obstacle_contact(self, message.normal, message.distance) --this causes the obsticle contact routine on line 92 to run

		elseif message.group == group_spike then
			handle_obstacle_contact(self, message.normal, message.distance)
			if self.enemy_contact == false then 
				player_damage(self, message.normal, message.distance)
			end

		elseif message.group == group_flag then
			self.level_complete = true
			sound.stop("/sound#sound")
			msg.post("/level_complete2#level_complete2", "time", {timer = timer})
			msg.post(".", "release_input_focus")
		end
	elseif message.group == group_enemy then
		if self.enemy_contact == false then
			player_damage(self, message.normal, message.distance)
		end
	end
end

I added the line that you put in which was timer.delay = nil and it returned


not sure if it’s of any use though… if you need the whole script I can send you a zipped copy if you like :slight_smile:

No no, sorry, I was unclear. The fact that timer.delay is nil is the issue in the first place.

However this error message highlights the problem. Somewhere, you have set set timer to be equal to a string. For example, doing this will not work:

local timer = "test"
timer.delay(3, false, function (self, handle, time_elapsed)
		print("hello")
		self.enemy_damage = false
	end)

Can’t see in the code you posted where that happens, but this is your problem.

1 Like

ohhh i think i know where this happens i have a timer which is used to time how long it takes the player to reach the end of the level. I have a timer gui that shows the current time on screen. It looks like this:

local function update_timer(self, dt)
	if self.level_complete == false then
		mins = math.floor(self.timer / 60)
		secs = self.timer % 60
		timer = string.format("%02d:%05.2f" ,mins, secs)
		msg.post("/clock#clock", "time", {timer = timer})
	end
end

this is used to send the time to the update timer function

	self.timer = self.timer + dt
	update_timer(self)

Yes, that overwrites timer. You need to name it something else.

2 Likes

i changed all the timer variable names above to clock and then changed the gui script to recieve messages of clock instead of timer and it worked. thank you so so much, you are absolutely amazing !!!

3 Likes

Remember to put local when declaring a variable:

local timer = string.format("%02d:%05.2f" ,mins, secs)

That way, you can call your variables whatever you want without accidentally overriding the built-in functions.

1 Like

That’s true, globally, but it would still overwrite timer in the local scope. Best to just use unique naming in the first place I would say to avoid these issues altogether.