Trying to create a system where an axe hits a tree, the tree loses hp, the whole tree dissapears

Godot Version

4.5

Question

END GOAL: [

Axe collides with tree

Tree loses health

Tree health hits zero and it is then deleted

]

OBSTICLE [

i dont know how im supposed to implement this damage/death system, im still not understanding, to the point where i dont know what i dont know

]

It would be a lot easier to ask for help if i knew what exactly i was doing wrong, but i kinda dont So, let me lay it all out for you, right now ive got everything in one scene, the scene has a couple components
an axe
a Tree

A timer

A node2D

The node2d spawns trees on a timer based off of a tree node i pre created that you cant see when the game first starts( i dont know too much about how all this works yet so im being thorough)

The func for making trees is this(Working without issue i think so you can just skim over it )

func NewNode(node_2d: Node2D) -> Node2D:
			Treecount = Treecount + 1
			var new_node2d: Node2D = node_2d.duplicate()
			#make a copy of the node you give it with random size
			new_node2d.scale = Vector2(randf_range(7.0,13.0), randf_range(7.0,13.0))
			new_node2d.position = Vector2(randf_range(0,1150), randf_range(0,650))
			#Trying to get the Sprite2D of the new copy
			var node2child : Sprite2D = node_2d.get_child(0)
	
			print(node2child)
			#random number to choose the version of the tree art to use 
			Treever = randi_range(1,3)
			
			print(Treever)
		
			if Treever == 1:
				node2child.texture = ResourceLoader.load("res://Png/TreeVerOne.png")
			if Treever == 2:
				node2child.texture = ResourceLoader.load("res://Png/TreeVerTwo.png")
			if Treever == 3:
				node2child.texture = ResourceLoader.load("res://Png/TreeVerThree.png")
			add_child(new_node2d)
			return new_node2d

This is the code for the axe(also seems to be working fine)

extends CharacterBody2D
@onready var Anim = $AnimatedSprite2D
@onready var Axe = $Node2D/Axe
const SPEED = 300.0
@export var Damage = 20 

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.

func get_input(): 
	var input_direction = Input.get_vector( "Left", "Right", "Up", "Down")
	velocity = input_direction * SPEED
	if velocity != Vector2(0,0) :
		Anim.play()
	else:
		Anim.pause()
func _ready() -> void:
	pass
func _physics_process(_delta):
	get_input()
	move_and_slide()

Now, i have An Area2D as a child of the axe, thats where i put the stuff for the damage

class_name Hitbox
extends Area2D

@onready var Hitboxowner = $".."
@export var Damage = 20 

func _init() -> void:
	collision_layer = 0
	collision_mask = 2

#you cant see it but this is connected to the tree`s area2D using the node button from the side pannel on the right side of the screen
func _on_hurtbox_area_entered(hurtbox: Area2D) -> void:
	print("Touched :", hurtbox)
	hurtbox.Health = hurtbox.Health - 20

Here is the code for the Tree, because i was struggling to get the damage to work, i put it in both parts

class_name Hurtbox

extends Area2D

@export var Health = 20

var Touched = []
var damage = 0
func _init() -> void:
	collision_layer = 2
	collision_mask = 0

#func _process(_delta: float) -> void:
	#Touched = get_overlapping_areas()
	#print(Touched)
	
	
#HERE is where the error hightlights
 # The error message reads "Invalid operands 'Nil' and 'int' in operator '-'"

func _on_hitbox_area_entered(area: Area2D) -> void:
	var AXE_DAMAGE = $"../../Node2D/Axe/Hitbox".Damage
	print("HITBOX TOUCH RECIEVED")
	var TIMBER = self.get_parent()
	Health = Health - AXE_DAMAGE
	print(Health)

	if Health <= 0:
		TIMBER.queue_free()

PS. was i using the terms hitbox/hurtbox correctly? its confusing

Where?

all of the code is above that part, writing mistake. ill fix it

Are you getting the Error when executing the game, or when the axe enters the hurtbox of the tree?

You’re doing 20 DMG and it only has 20 HP so it might be working as intended.

Try changing tree hp to 40 and see if it takes two swings.

Better yet, put a print under your trees take damage function and print("damage taken: " , damage) so you can see that in addition to the health.

Is your health printing 0?

Also is it possible one swing of the axe is hitting multiple times? You can add hot boxes to an array and ignore them for the remainder of the swing. Or a super easy way to do it is to just disable it then turn it back on with a timer. Array is probably better tho

Oh also, it looks like you might be calling damage in your hit box under the hurt box area entered line and then again in the actual hurt box.

Maybe triple check that’s not leading to issues for you.

Sorry for the long response time. im seeing the error as soon as the axe hits the tree

If this last line is your only error then maybe your Damage has been saved as null instead of an integer value, this is kind of a bug with the editor as far as I’ve seen. Try adding types to your exports to be extra safe

                 # v---v
@export var Damage: int = 20

Otherwise I’d assume your AXE_DAMAGE path is bad, and using ../ in a path is generally bad. If you anticipate the axe area to be the one overlapping this hitbox area, then that’s what the passed-in area variable represents and you can use that instead of a crazy path.

func _on_hitbox_area_entered(area: Area2D) -> void:
	print("HITBOX TOUCH RECIEVED")

	# only trigger if a child of node named Axe overlapped
	if area.get_parent().name == "Axe":
		var TIMBER = self.get_parent()
		var AXE_DAMAGE: int = area.Damage
		Health = Health - AXE_DAMAGE

It does seem like you’re flailing signal connections around, you should only need one signal to detect these collisions. The Hurtbox’s area_entered connected to itself. You can then filter out what hit the hurtbox using if and the provided area such as my sample comparing the parent’s name.

You may be getting errors from other superfluous connections and/or double-damage glitches

after setting the type to int for the hp and damage it stopped giving me that error, only to then give me an error because it cannot duplicate null( spawn a new tree, since ig i deleted the tree that was supposed to be there for cloning). im gonna watch a couple more tutorials. thank you for the help.