Help me with my killzone

Godot Version

4.3

Question

I’m making a killzone script for my new game but when I tested it my game crashed pls help, here’s the code.

extends Area2D

#variables

@onready var health = 20
@onready var timer = $Timer
@onready var damaged = true
@onready var lambdas_ref = func _on_timer_timeout() -> void:
	damaged = true

#functions

func _on_body_entered(body: Node2D) -> void:
	while(damaged):
		health -= 1 #<-- subtracts health
		var damaged = false
		timer.start
		print(health)
	
	if health <= 0:
		health = 0
		print("You Died!")
		get_tree().reload_current_scene()
		
	elif health <= 10:
		print("You Are Hurt.")
		
	else:
		print("You Are Fine.")

What’s the crash?

Ah, ok. Have a look at this:

var damaged = true

[...]

while(damaged):
    [...]
    var damaged = false # OOPS
    [...]

You’ve got var damaged in the while loop. That makes a new variable in that scope called damaged and assigns false to it, but the while() loop is operating on the global scope damaged. The loop will never end.

My suggestions:

  • make that while() an if – it’s not intentionally being used to loop
  • strip var off var damaged inside _on_body_entered()

Thanks but now the killzone just damages the player once but I want it to keep taking 1 health off every second spent in the killzone. If I wanted that to happen the I wouldn’t have the lambda.

You should try a for loop.
Also, is your character being handled in a class? if so you could probably set up a death function & have it be public, so if you change anything about the death screen/function, then you won’t have to modify a lot of scripts.

Also to avoid putting the script in a lot of bodies, you should have another for loop iterate and add a key (in this case, body) to a dictionary full of bodies (or you can manually place them), and then have a general on body entered function, where it checks if the body is a member of the bodies dictionary.
It might be much, but it saves you from having to plant the script into every new body.

In that case, you probably want to do this differently. It looks like you’re checking if the area was entered and then firing this off. What you probably want to do is, every update check if you’re within the area, and do a bit of damage if so.

A loop inside the function is going to run to completion within a single update, which will be an instant kill.

could you show what that code could look like?

For example:

const DAMAGE_PER_SEC =  5.0
const REGEN_PER_SEC  =  0.1
const MAX_HEALTH     = 20.0

var body_is_in = false
var health     = MAX_HEALTH

func _on_body_entered(body: Node2D) -> void:
    body_is_in = true

func _on_body_exited(body: Node2D) -> void:
    body_is_in = false

func _process(delta: float) -> void:
    if body_is_in:
        health -= DAMAGE_PER_SEC * delta
    elif health < MAX_HEALTH:
        health = clampf(health + (REGEN_PER_SEC * delta), 0.0, MAX_HEALTH)

    if health <= 0.0:
        print("O! I Die!")