Invalid call. Nonexistent function 'take_damege' in base 'Node2D'.

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By R0dL0d

hi, i’m doing a game candy-crush like for a school project. And i have gotten this error:
Invalid call. Nonexistent function ‘take_damege’ in base ‘Node2D’.

Apparently i have a function that my script is not reading. They are separated in two scripts but i don’t think thats the problem. the two codes:

 func _on_Grid_damage_ice(board_position):
	if ice_pieces[board_position.x][board_position.y] != null:
		ice_pieces[board_position.x][board_position.y].take_damage(1)
		if ice_pieces[board_position.x][board_position.y].health <= 0:
			ice_pieces[board_position.x][board_position.y].queue_free()
			ice_pieces[board_position.x][board_position.y] = null

and

export (int) var health

func _ready():
	pass # Replace with function body.

func take_damage(damage):
	health <= damage

So the “take_damage” is been call invalid for some reason
anything that can help i would be grateful.

Edit: heres the principal script:

#state machine
enum {wait, move}
var state

# Grid Variaveis
export (int) var width;
export (int) var height;
export (int) var x_start;
export (int) var y_start;
export (int) var offset;
export (int) var y_offset;

# obstacle Stuff
export (PoolVector2Array) var empty_spaces
export (PoolVector2Array) var ice_spaces

#obstacle signals
signal damage_ice
signal make_ice

#The piece array
var possible_pieces = [
preload("res://Cenario peças/banana.tscn"),
preload("res://Cenario peças/dragao.tscn"),
preload("res://Cenario peças/melancia.tscn"),
preload("res://Cenario peças/tomato.tscn"),
preload("res://Cenario peças/maça.tscn"),
preload("res://Cenario peças/uva.tscn")	
];

# the current  pieces in the scene
var all_pieces =[];

#swap back variable
var piece_one = null
var piece_two = null
var last_place = Vector2(0,0)
var last_direction = Vector2(0, 0)
var move_checked = false
# Touch variable
var first_touch  = Vector2(0, 0);
var final_touch  = Vector2(0, 0);
var controlling = false;

func _ready():
	state = move
	randomize();
	all_pieces  = make_2d_array();
	spawn_pieces();
	spawn_ice();
	
func restricted_fill(place):
	#check thepty pieces
	if is_in_array(empty_spaces, place):
		return true
	return false	
	
			
	
func is_in_array(array, item):
	for i in array.size():
		if array[i] == item:
			return true
	return false			
	
func make_2d_array():
	var array = [];
	for i in width:
		   array.append([]);
		   for j in height:
			   array[i].append(null)
	return array;
	
func spawn_pieces():
	for i in width:
		for j in height:
			if !restricted_fill(Vector2(i, j)):
			#choose a random number and store it
				var rand = floor(rand_range(0, possible_pieces.size()));
				var piece = possible_pieces[rand].instance();
				var loops = 0
				while(match_at(i, j, piece.color) && loops < 100):
					rand = floor(rand_range(0, possible_pieces.size()));
					loops += 1;
					piece = possible_pieces[rand].instance();
			#instance that piece from the array
				add_child(piece);
				piece.position = grid_to_pixel(i, j);
				all_pieces[i][j] = piece;
				print (possible_pieces[rand])

func spawn_ice():
	for i in ice_spaces.size():
		emit_signal("make_ice", ice_spaces[i])
	

func match_at(i, j, color):
	
	if i > 1:
		if all_pieces[i - 1][j] != null && all_pieces[i - 2][j] != null:
			if all_pieces[i - 1][j].color == color && all_pieces[i - 2][j].color == color:
				return true;
	if j > 1:
		if all_pieces[i][j - 1] != null && all_pieces[i][j - 2] != null:
			if all_pieces[i][j - 1].color == color && all_pieces[i][j - 2].color == color:
				return true;
				
	
func grid_to_pixel(column, row):
	var new_x = x_start + offset * column;
	var new_y = y_start + -offset * row;
	return Vector2(new_x, new_y);
	
func pixel_to_grid(pixel_x, pixel_y):
	var new_x = round((pixel_x - x_start) / offset);
	var new_y = round((pixel_y - y_start) / -offset);
	return Vector2(new_x, new_y);
	pass;	
	
func is_in_grid(grid_position):
	if grid_position.x >= 0 && grid_position.x < width:
		if grid_position.y >= 0 && grid_position.y < height:
			return true;
	return false;			
	
func touch_input():
	
	if Input.is_action_just_pressed("ui_touch"):		
		if is_in_grid(pixel_to_grid(get_global_mouse_position().x, get_global_mouse_position().y)):
			first_touch = pixel_to_grid(get_global_mouse_position().x, get_global_mouse_position().y);
			controlling = true
	if Input.is_action_just_released("ui_touch"):
		if is_in_grid(pixel_to_grid(get_global_mouse_position().x, get_global_mouse_position().y)) && controlling:
			controlling = false;
			final_touch= pixel_to_grid(get_global_mouse_position().x, get_global_mouse_position().y)
			touch_difference(first_touch, final_touch);

func swap_pieces(column, row, direction):			
	var first_piece = all_pieces[column][row];
	var other_piece = all_pieces[column + direction.x][row + direction.y];
	if first_piece != null && other_piece != null:
		store_info(first_piece, other_piece, Vector2(column, row), direction)
		state = wait
		all_pieces[column][row] = other_piece;
		all_pieces[column + direction.x][row + direction.y] = first_piece;
		first_piece.move(grid_to_pixel(column + direction.x, row + direction.y));
		other_piece.move(grid_to_pixel(column, row));
		if !move_checked:
			find_matches()
	
func store_info(first_piece, other_piece, place, direction):
	piece_one = first_piece
	piece_two = other_piece
	last_place = place
	last_direction = direction
	pass
func swap_back():
	#LOL
	if piece_one != null && piece_two != null:
		swap_pieces(last_place.x, last_place.y, last_direction)
	state = move
	move_checked = false
	pass
			
func touch_difference(grid_1, grid_2):
	var difference = grid_2 - grid_1;
	if abs(difference.x) > abs(difference.y):
		if difference.x > 0:
			swap_pieces(grid_1.x, grid_1.y, Vector2(1, 0));
		elif difference.x < 0:
			swap_pieces(grid_1.x, grid_1.y, Vector2(-1, 0));
	elif abs(difference.y) > abs(difference.x):
		if difference.y > 0:
			swap_pieces(grid_1.x, grid_1.y, Vector2(0, 1));
		elif difference.y < 0:
			swap_pieces(grid_1.x, grid_1.y, Vector2(0, -1));
		pass;
	
func _process(delta):
	if state == move:
		touch_input();
	
	
func find_matches():
	for i in width:
		for j in height:
			if all_pieces[i][j] != null:
				var current_color = all_pieces[i][j].color
				if i > 0 && i < width - 1:
					if !is_piece_null(i - 1, j) && all_pieces[i + 1][j] != null:
						if all_pieces[i - 1][j].color == current_color && all_pieces[i + 1][j].color == current_color:
							match_and_dim(all_pieces[i - 1][j])
							match_and_dim(all_pieces[i][j])
							match_and_dim(all_pieces[i + 1][j])
							all_pieces[i][j].matched = true;
							all_pieces[i][j].dim();
							all_pieces[i + 1][j].matched = true;
							all_pieces[i + 1][j].dim();
				if j > 0 && j < height - 1:
					if all_pieces[i][j - 1] != null && all_pieces[i][j + 1] != null:
						if all_pieces[i][j - 1].color == current_color && all_pieces[i][j + 1].color == current_color:
							match_and_dim(all_pieces[i][j - 1])
							match_and_dim(all_pieces[i][j])
							match_and_dim(all_pieces[i][j + 1])
							all_pieces[i][j].matched = true;
							all_pieces[i][j].dim();
							all_pieces[i][j + 1].matched = true;
							all_pieces[i][j + 1].dim();
	get_parent()	.get_node("destroy_timer").start()	
	
	
func is_piece_null(column, row):
	if all_pieces[column][row] == null:
		return true
	return false	
		
	
func match_and_dim(item):
	item.matched = true
	item.dim()
									

func destroy_matched():
	var was_matched = false
	for i in width:
		for j in height:
			if all_pieces[i][j] != null:
				if all_pieces[i][j].matched:
					emit_signal("damage_ice", Vector2(i,j))
					was_matched = true
					all_pieces[i][j].queue_free()
					all_pieces[i][j] = null
	move_checked = true
	if was_matched:
		get_parent().get_node("Collapse_timer").start()
	else:	
		swap_back()
func collapse_collums():
	for i in width:
		for j in height:
			if all_pieces[i][j] == null && !restricted_fill(Vector2(i, j)):
				for k in range(j + 1, height):
					if all_pieces[i][k] != null:
						all_pieces[i][k].move(grid_to_pixel(i, j))
						all_pieces[i][j] = all_pieces[i][k]
						all_pieces[i][k] = null
						break
	get_parent().get_node("refil_timer").start()						
func refill_columns():
	for i in width:
		for j in height:
			if all_pieces[i][j] == null && !restricted_fill(Vector2(i, j)):
				var rand = floor(rand_range(0, possible_pieces.size()));
				var piece = possible_pieces[rand].instance();
				var loops = 0
				while(match_at(i, j, piece.color) && loops < 100):
					rand = floor(rand_range(0, possible_pieces.size()));
					loops += 1;
					piece = possible_pieces[rand].instance();
				#instance that piece from the array
				add_child(piece);
				piece.position = grid_to_pixel(i, j - y_offset);
				piece.move(grid_to_pixel(i, j));
				all_pieces[i][j] = piece;
	after_refil()

func after_refil():
	for i in width:
		for j in height:
			if all_pieces[i][j] != null:
				if match_at(i, j, all_pieces[i][j].color):
					find_matches()
					get_parent().get_node("destroy_timer").start()
					return
	state = move
	move_checked = false

func _on_destroy_timer_timeout():
	destroy_matched()

func _on_Collapse_timer_timeout():
	collapse_collums()

func _on_refil_timer_timeout():
	refill_columns()

Pieces script:

    export (String) var color;
var move_tween;
var matched = false


func _ready():
	move_tween = get_node("Sprite/move_tween")
	
	pass # Replace with function body.

func move(target):
	move_tween.interpolate_property(self, "position", position, target, .3,
								   Tween.TRANS_BOUNCE, Tween.EASE_OUT);
	move_tween.start();
	pass;

# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
#	pass

func dim():
	var sprite = get_node("Sprite")
	sprite.modulate = Color(1, 1, 1, .5);
	pass
:bust_in_silhouette: Reply From: Wakatta

Pretex

Computers are not very good at understanding human speech Alpha-Numeric Languages similar to most people not being able to understand machine code binary.

Program Languages are a way to mediate this gap by translating one to the other however what is typed must conform strictly to the guidelines or your intentions will get lost in translation.

Problems

  1. The most common problems while programming are caused by user error of sometimes simply misspelling a word
  2. Which based on your title is the most likely candidate for your error.
  3. This line health <= damage does not do anything
  4. You’ve offset critical info outside of the function
  5. Global variable misuse [avoid when possible the use of global vars and never manipulate them outside of their class directly]

Semi - Solution

export (int) var health

func _ready():
    pass # Replace with function body.

func take_damage(damage):
    health -= damage

    if health <= 0:
        queue_free()

    return health

Nothing is wrong with your use case however you can use Vector2 in lieu of multiple Arrays

func _on_Grid_damage_ice(board_position : Vector2):
    if ice_pieces[board_position] != null:
        ice_pieces[board_position].take_damage(1)
        if ice_pieces[board_position].health <= 0:
            ice_pieces[board_position] = null

yeah. the error is gone but, the index “broken” or something.

Invalid get index ‘(1, 1)’ (on base: ‘Array’).

something to do with the grid i have to the pieces of the game…
the (1, 1) change every time that i restart the game so is not a particular piece i think
if this help i can post the entire grid script to see is something is wrong.

ps: i don’t know so much about godot or programin… i’m sorry if this is a easy error to solve :stuck_out_tongue:

R0dL0d | 2022-11-04 21:56

Yes please provide if you can.

Wakatta | 2022-11-05 08:32

I put the codes in edit, the first is the main script, and the second is the script of the pieces itself

R0dL0d | 2022-11-05 16:10

Wow you’ve shown all your code except the critical piece. Like the file that includes the following.

func _on_Grid_damage_ice(board_position):
    if ice_pieces[board_position.x][board_position.y] != null:
        ice_pieces[board_position.x][board_position.y].take_damage(1)
        if ice_pieces[board_position.x][board_position.y].health <= 0:
            ice_pieces[board_position.x][board_position.y].queue_free()
            ice_pieces[board_position.x][board_position.y] = null

Wakatta | 2022-11-06 09:55

So. this is just code i put in the first script. is something that can change to fix the problem?

R0dL0d | 2022-11-07 00:59

This is the file causing the problem Yeah?

for one the way you interact with ice_pieces is very important in finding a resolution

Wakatta | 2022-11-07 20:35

i don’t think i am understanding. So i will say the error again.
the code:

func _on_Grid_damage_ice(board_position : Vector2):
if ice_pieces[board_position] != null:
	ice_pieces[board_position].take_damage(1)
	if ice_pieces[board_position].health <= 0:
		ice_pieces[board_position] = null

is gettin the error:

Invalid get index ‘(X, Y)’ (on base: ‘Array’).

on the line that the error is markin:

if ice_pieces[board_position] != null:

another two errors on the lines of the principal script:
‘‘func destroy_matched():’’

emit_signal("damage_ice", Vector2(i,j))

and:
‘‘func _on_destroy_timer_timeout():’’

destroy_matched()

idk if this helps but in need something that can help solve the error i can assist.

R0dL0d | 2022-11-08 11:57

You’ve shown 2 scripts

  • Principal.gd
  • Pieces.gd

and none of them contain this var ice_pieces or this function _on_Grid_damage_ice which are creating the problem that you’re having

This line

Invalid get index ‘(X, Y)’ (on base: ‘Array’).

is caused by the way your ice_pieces var is created then accessed

for example your all_pieces var is created using

for i in width:
    for j in height:
        if all_pieces[i][j] != null:

so to access it you’ll have todo

var piece = all_pieces[width][height]

but if you tried todo

var piece = all_pieces[Vector2(width, height)]

it will throw an error

Wakatta | 2022-11-08 16:09

ok.
sorry if i don’t uderstand. idk so much about programin stuff.

so all i have todo is call the ice pieces and the _on_Grid_damage_ice in the principal script?

sorry again, i’m not one of the smart ones.

R0dL0d | 2022-11-08 21:11

No provide the script that contain these two concepts so your issue can be resolved

Wakatta | 2022-11-09 12:45

ok sorry again, here it is:

var ice_pieces = []
var width = 8
var height = 10
var ice = preload("res://Cenarioo/Gelo.tscn")
var health

# Called when the node enters the scene tree for the first time.
func _ready():
	pass
	
func make_2d_array():
	var array = [];
	for i in width:
		  array.append([]);
		  for j in height:
			   array[i].append(null)
	return array;


func _on_Grid_make_ice(board_position):
	if ice_pieces.size() == 0:
		ice_pieces = make_2d_array()
	var current = ice.instance()
	add_child(current)
	current.position = Vector2(board_position.x * 64 + 64, -board_position.y * 64 + 800)
	ice_pieces[board_position.x][board_position.y] = current
	
func take_damage(damage):
	
	health -= damage

	if health <= 0:
		queue_free()

	return health


func _on_Grid_damage_ice(board_position : Vector2):
	if ice_pieces[board_position] != null:
		ice_pieces[board_position].take_damage(1)
		if ice_pieces[board_position].health <= 0:
			ice_pieces[board_position] = null
			
			

plus i got 1 script variable that got the ice in the grid…
is in the principal script

export (PoolVector2Array) var ice_spaces

if need something else i can provide ;D

R0dL0d | 2022-11-09 13:17

Finally now it all makes sense.

With the limited information provided before you got a limited answer

Invalid call. Nonexistent function take_damage

You got that error because your ice instances do not have that function

You also need to Move the function take_damage to the Pieces scriptas well as the health var

Answer

var ice_pieces = []
var width = 8
var height = 10
var ice = preload("res://Cenarioo/Gelo.tscn")

func make_2d_array():
	var array = []
	for i in width:
		  array.append([])
		  for j in height:
			   array[i].append(null)
	return array

func _on_Grid_make_ice(board_position):
	if ice_pieces.size() == 0:
		ice_pieces = make_2d_array()
	var current = ice.instance()
	add_child(current)
	current.position = Vector2(board_position.x * 64 + 64, -board_position.y * 64 + 800)
	ice_pieces[board_position.x][board_position.y] = current

func _on_Grid_damage_ice(board_position):
	if ice_pieces[board_position.x][board_position.y] != null:
		ice_pieces[board_position.x][board_position.y].take_damage(1)

There is no need for the next line because queue_free() in the ice instance will clear its reference in the array

ice_pieces[board_position.x][board_position.y] = null

And in the Pieces script

export (String) var color
var move_tween
var matched = false
var health

func _ready():
	move_tween = get_node("Sprite/move_tween")

func move(target):
	move_tween.interpolate_property(self, "position", position, target, .3,
								   Tween.TRANS_BOUNCE, Tween.EASE_OUT)
	move_tween.start()

func dim():
	var sprite = get_node("Sprite")
	sprite.modulate = Color(1, 1, 1, .5)

func take_damage(damage):

	health -= damage

	if health <= 0:
		queue_free()

	return health

Wakatta | 2022-11-11 14:50

I think that fixed the error of the index. but the “take_damage” error returned, there’s a chance I put the code wrong, so I’ll post the end of the code I made… sorry for taking your time.

var ice_pieces = []
var width = 8
var height = 10
var ice = preload("res://Cenarioo/Gelo.tscn")

func make_2d_array():
	var array = []
	for i in width:
		  array.append([])
		  for j in height:
			   array[i].append(null)
	return array

func _on_Grid_make_ice(board_position):
	if ice_pieces.size() == 0:
		ice_pieces = make_2d_array()
	var current = ice.instance()
	add_child(current)
	current.position = Vector2(board_position.x * 64 + 64, -board_position.y * 64 + 800)
	ice_pieces[board_position.x][board_position.y] = current

func _on_Grid_damage_ice(board_position):
	if ice_pieces[board_position.x][board_position.y] != null:
    ice_pieces[board_position.x][board_position.y].take_damage(1)	
    ice_pieces[board_position.x][board_position.y] = null

R0dL0d | 2022-11-11 20:39

ice_pieces[board_position.x][board_position.y] = null

No need for that line

Also double check that your "res://Cenarioo/Gelo.tscn" has the pieces script attached to the top most node in that scene

Add this function check as well

func _on_Grid_damage_ice(board_position):
    if ice_pieces[board_position.x][board_position.y] != null:
    if ice_pieces[board_position.x][board_position.y].has_method("take_damage"):
        ice_pieces[board_position.x][board_position.y].take_damage(1) 

Wakatta | 2022-11-11 20:54

fix the error, but i don’t do what it supose todo… do you know something that i can put to make the sprite disappear?

R0dL0d | 2022-11-12 00:04

You already have with queue_free()

Will try your code and see if it works and get back to you

Wakatta | 2022-11-12 21:56

any progress? i know its late to say now. But this code is from a tutorial. if you need more information about the code i think you can find is this video:
https://www.youtube.com/watch?v=ThINCQcEOYs

R0dL0d | 2022-11-16 12:21

Figured as much.

And with that knowledge provided there was never ever any reason for me to help you in the first place because all the code for your project is right here and all of the steps are equally located here

After downloading that code if you don’t already have one you should download a versioning diff tool like Meld then compare your project to the one above and it will show exactly where you misstep.

Additionally if you intend to do coding continually you could get familiar with version control software such as Git to properly manage your future projects

Wakatta | 2022-11-17 22:26