I have a problem with damage registration

Godot 4.5.1

Question

I have a problem with damage registration, i call check_overlapping_areas method at 1 keyframe in AnimationPlayer’s animation, but it deal damage first 3 times, later 2 times always. Damage realize by global signal enemy_got_damage, so:

weapon script to deal damage (only func):

func check_overlapping_areas():	
	await get_tree().process_frame
	var overlapping_areas = $AttackArea.get_overlapping_areas()
	var enemies_group = get_tree().get_nodes_in_group("Enemies_Group")
	var enemies_group_size = enemies_group.size()

	var i = 0
	while i < enemies_group_size:
		
		if enemies_group[i] in overlapping_areas:
			
			GlobalScript.enemy_got_damage.emit(DAMAGE, enemies_group[i])
		
		i += 1
		if i >= enemies_group_size:
			i = 0
			break

enemy’s script to receiving damage (only func, .callable() for signal in _ready() func):

func on_enemy_got_damage(Damage, enemy):
	if enemy.get_parent().HP <= 0:
		enemy.get_parent().queue_free()
	enemy.get_parent().HP -= Damage

(if its need, game is 2d)

Who and when starts this animation?

Weapon start animation, from 0.15s to 0.3s weapon enable collision for area, all other times of animation collision disable. Keyframe to func check_overlapping_areas is on 0.151s only

Yes, but calls play() for this animation?

func _physics_process(delta: float) -> void:
	if Input.is_action_just_pressed("attack"):
		$AnimationPlayer.play("Attack1")

this func in weapon’s script

Put print statements in check_overlapping_areas() and on_enemy_got_damage() to see how and when are they getting called.

its where i put print:

weapon script:

func check_overlapping_areas():	
	await get_tree().process_frame
	var overlapping_areas = $AttackArea.get_overlapping_areas()
	var enemies_group = get_tree().get_nodes_in_group("Enemies_Group")
	var enemies_group_size = enemies_group.size()
	var i = 0
	while i < enemies_group_size:
		print(2)
		if enemies_group[i] in overlapping_areas:
			print(1)
			GlobalScript.enemy_got_damage.emit(DAMAGE, enemies_group[i])
		
		i += 1
		if i >= enemies_group_size:
			print(3)
			i = 0
			break

enemy script:

func on_enemy_got_damage(Damage, enemy):
	print(4)
	if enemy.get_parent().HP <= 0:
		print(5)
		enemy.get_parent().queue_free()
		print(6)
	enemy.get_parent().HP -= Damage

and this is what print in console:
2
2
2
1
4
4
4
5
6
3

Print relevant information instead of numbers, like values of variables.

func check_overlapping_areas():	
	await get_tree().process_frame
	var overlapping_areas = $AttackArea.get_overlapping_areas()
	var enemies_group = get_tree().get_nodes_in_group("Enemies_Group")
	var enemies_group_size = enemies_group.size()
	var i = 0
	while i < enemies_group_size:
		print(enemies_group, enemies_group_size, overlapping_areas)
		if enemies_group[i] in overlapping_areas:
			print(enemies_group[i])
			GlobalScript.enemy_got_damage.emit(DAMAGE, enemies_group[i])
		
		i += 1
		if i >= enemies_group_size:
			i = 0
			break
func on_enemy_got_damage(Damage, enemy):
	print(Damage, enemy)
	if enemy.get_parent().HP <= 0:
		enemy.get_parent().queue_free()
	enemy.get_parent().HP -= Damage

console:

[BodyHitbox:<Area2D#78232162135>, BodyHitbox:<Area2D#78416711522>, BodyHitbox:<Area2D#78601260909>]3[BodyHitbox:<Area2D#78232162135>]
BodyHitbox:<Area2D#78232162135>
20BodyHitbox:<Area2D#78232162135>
20BodyHitbox:<Area2D#78232162135>
20BodyHitbox:<Area2D#78232162135>
[BodyHitbox:<Area2D#78232162135>, BodyHitbox:<Area2D#78416711522>, BodyHitbox:<Area2D#78601260909>]3[BodyHitbox:<Area2D#78232162135>]
[BodyHitbox:<Area2D#78232162135>, BodyHitbox:<Area2D#78416711522>, BodyHitbox:<Area2D#78601260909>]3[BodyHitbox:<Area2D#78232162135>]

If on_enemy_got_damage() is connected to the global signal for each enemy, then your code will call it on all enemies whenever any enemy gets hit. So if you have 3 enemies in total, on_enemy_got_damage() will run on all of them.

ok, but how to fix that? im newbie and i dont know, and i need to put more than 1 enemy at a time

You may think about using a different approach to handle/organize signals, but a quick fix would be to check if the enemy argument you got in the signal handler is actually the enemy that the script is attached to, and apply the damage only if that’s true.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.