0 votes

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!

in Engine by (19 points)

1 Answer

0 votes
Best answer
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.

by (28,778 points)
selected by

It worked! :D Thank you so much

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.