Problem with timer not starting + changing a variable from a different script

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

Hello,
I am making a game with 2 characters, the player and a zombie. I want to make the player damaged when the zombie collides with the player. Here’s my code

player.gd

var max_health = 6
onready var health = max_health setget _set_health

func damage(amount):
if invulnerability_timer.is_stopped():
	invulnerability_timer.start
	_set_health(health - amount)
	effects_animation.play("damage")
	effects_animation.queue("invulnerability")

func kill():
	print("dead")

func _set_health(value):
	var prev_health = health
	health = clamp(value, 0, max_health)
	if health != prev_health:
		emit_signal("health_update", health)
		if health == 0:
			kill()

func on_invulnerabilitytimer_timeout() -> void:
	effects_animation.play("rest")

zombie.gd

onready var player = preload("res://player.gd").new()

for i in get_slide_count():
	var collision = get_slide_collision(i)
	if collision.collider.name == "player":
		player.damage(1)

I am using the code from Game Endeavor’s tutorial for the player. What it does is subtract from the player’s total health then give the player a short amount of time of invulnerability. When I test the code out by making the player damaged when it collides with the zombie. Everything works just fine except for the timer which doesn’t start for some reason. And when I run the game with the code above, it crashes and says "Invalid call. Nonexistent function ‘is_stopped’ in base ‘Nil’.
Please help me fix my issue. I’m not a native speaker so my wording in some cases might be confusing. Thanks in advance!

:bust_in_silhouette: Reply From: Zylann
invulnerability_timer.start

There are missing () at the end of this line.

onready var player = preload("res://player.gd").new()

This line creates a new instance of a player stored inside a variable, one for each zombie you have, which won’t even be in the scene tree. Did you mean to get a reference to the existing player within the scene instead? You may want to consider get_node() or some other mean of accessing the player. Since you use collisions, perhaps you could do this instead:

for i in get_slide_count():
    var collision = get_slide_collision(i)
    # This tests that the collider IS the player
    if collision.collider.name == "player":
        # So you can actually just call the function on it directly
        collision.collider.damage(1)

If Godot tells you the damage() function doesnt exist on the collider, try collider.get_parent() instead (which should give you its physics body).

"Invalid call. Nonexistent function ‘is_stopped’ in base ‘Nil’.

It means the invulnerability_timer variable is null. You may check how you are initializing it. However, I assume that because of the previous problem I mentionned, those “player” instances never entered the tree so were never _ready.

It worked! :smiley: Thank you so much

mynamesdat | 2020-02-29 00:48