How to get an enemy to attack the player if the player already is within distance

Godot Version

V. 4.2.1

Question

I’m creating an enemy for a game and having a bit of trouble. The enemy has a weapon and attacks when the player enters the “start attack area” but if the player enters “start area attack shape” in the last frames when enemy isn’t damaging the player, the skeleton won’t attack again and will keep walking forward into the player

Skeleton enemy script:

#things to do:
#1
	#if player enters "start area attack shape" in the last frames when enemy isn't 
	#damaging the player, the skeleton won't attack again and will keep walking forward




extends CharacterBody2D

#-------------------------------------------
const speed = 50
#-------------------------------------------
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
var chase = false
var is_attacking = false
var playback : AnimationNodeStateMachinePlayback
#-------------------------------------------
@onready var player = get_node("../../Player/Player")
@onready var skeleton = $"."
@onready var animation_tree: AnimationTree = $AnimationTree
@onready var health = $Damageable_skeleton.Skeleton_health
@onready var state_machine = $AnimationTree.get("parameters/playback")
#-------------------------------------------



func _on_ready():
	add_to_group("enemy")
	animation_tree.active = true


func _process(_delta):
	update_animation_parameters()
	if is_attacking == false:
		$Attack_area.monitoring = false
#adds skeleton to enemy group
	if $".".is_in_group("enemy") != true:
		add_to_group("enemy")
	print(is_attacking)


#physics
func _physics_process(delta):
	if not is_on_floor():
		velocity.y += gravity * delta
	move_and_slide()
	var direction = (player.position - self.global_position).normalized()
	if chase == true:
		velocity.x = direction.x * speed
	if direction.x < 0:
		get_node("AnimatedSprite2D").flip_h = true
		$Attack_area.scale.x = -1
		$Start_attack_area.scale.x = -1
	else:
		get_node("AnimatedSprite2D").flip_h = false
		$Attack_area.scale.x = 1
		$Start_attack_area.scale.x = 1


#-------------------------------------------
#chasing the player
func _on_detection_area_body_entered(body):
	if body.is_in_group("Player_body"):
		chase = true

func _on_detection_area_body_exited(body):
	if body.is_in_group("Player_body"):
		chase = false
		velocity.x = 0


#animation state machine
func update_animation_parameters():
	if(velocity.x == 0):
		animation_tree["parameters/conditions/Idle"] = true
		animation_tree["parameters/conditions/is_moving"] = false
	elif(velocity.x != 0):
		animation_tree["parameters/conditions/Idle"] = false
		animation_tree["parameters/conditions/is_moving"] = true


	if $Damageable_skeleton.Skeleton_health == 0:
		velocity.x = 0
		state_machine.travel("Death")
		animation_tree["parameters/conditions/is_attacking"] = false
		animation_tree["parameters/conditions/Dead"] = true


	if is_attacking == true and $Attack_area.monitoring == true:
		Game.playerHP -= 3
	while animation_tree["parameters/conditions/is_attacking"] == true:
		velocity.x = 0
#if skeleton isn't dead finish animation then set condition to false
		if animation_tree["parameters/conditions/Dead"] != true:
			await animation_tree.animation_finished
			animation_tree["parameters/conditions/is_attacking"] = false


func _on_start_attack_area_body_entered(body):
	if body.is_in_group("Player_body"):
		is_attacking = true
		animation_tree["parameters/conditions/is_attacking"] = true






func _on_start_attack_area_body_exited(_body):
	is_attacking = false

I’ve thought about creating a queue system, but I think the real issue is just my unoptimised code

Any and all help is appreciated

i think the easiest method is to connect the signal “animation_finished” to the script and check if its the attack animation and if its true check if the player is still in range. If yes then attack again

2 Likes

Thank you man!

1 Like

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