Godot Version
4.6.2 stable
Question
I am making a 2D rpg game but the problem is when i attack the enemy at a certain frame of the attack animation the enemy is completely invincible to dmg i tried everything to my knowledge but to no avail please help kind sirs.
""" Skeleton code
extends CharacterBody2D
@onready var animated = $AnimatedSprite2D
@onready var hitbox = $Hitbox
const knockback_power = 500
const SPEED: float = 0.4
var is_attacking: bool = false
var can_be_hit: bool = true
var is_hurt: bool = false
var facing_right: bool = true
var knockback: Vector2 = Vector2.ZERO
var overlapping_hitbox = null
var target = null
var skeleton: Dictionary = {
"atk" : 10,
"hp" : 100,
"def" : 2,
}
func _physics_process(_delta):
knockback = knockback.move_toward(Vector2.ZERO, 20)
velocity = knockback
if target and not is_hurt and not is_attacking:
_movement(_delta)
_facing()
animated.play("Run")
if overlapping_hitbox != null and overlapping_hitbox.monitoring and can_be_hit and not is_hurt:
_take_hit()
move_and_slide()
func _take_hit():
var player = overlapping_hitbox.get_parent()
var direction = (global_position - player.global_position).normalized()
is_hurt = true
is_attacking = false
can_be_hit = false
var died = false
if overlapping_hitbox.name == "Hitbox_PA":
died = damaged(player.knight["atk"], 2.0)
else:
died = damaged(player.knight["atk"])
if not died:
animated.play("Hurt")
knockback = direction * knockback_power
func _on_hurt_box_area_entered(area):
if area.is_in_group("player_hitbox"):
overlapping_hitbox = area
func _on_hurt_box_area_exited(area):
if area.is_in_group("player_hitbox"):
overlapping_hitbox = null
func damaged(atk, multiplier = 1.0):
var total_damage = (atk - skeleton["def"]) * multiplier
skeleton["hp"] -= total_damage
print("Skelly only have %d left" % skeleton["hp"])
if skeleton["hp"] <= 0:
skeleton["hp"] = 0
animated.play("Death")
return true
return false
func _on_animated_sprite_2d_animation_finished():
if animated.animation == "Death":
queue_free()
return
is_hurt = false
is_attacking = false
can_be_hit = true
if target:
animated.play("Run")
else:
animated.play("Idle")
func _facing() -> void:
var direction = target.position - position
if direction.x > 0:
animated.flip_h = false
facing_right = true
elif direction.x < 0:
facing_right = false
animated.flip_h = true
if facing_right:
hitbox.position.x = abs(hitbox.position.x)
else:
hitbox.position.x = -abs(hitbox.position.x)
func _movement(delta: float) -> void:
var direction = target.position - position
position += direction * delta * SPEED
func _on_sight_body_entered(body):
if body.name == "Knight":
target = body
func _on_sight_body_exited(body):
if body.name == "Knight":
target = null
if not is_hurt and not is_attacking:
animated.play("Idle")
func _on_hitbox_area_entered(area):
if not is_attacking and not is_hurt:
is_attacking = true
await get_tree().create_timer(0.3).timeout
if is_hurt:
return
if randi() % 2 == 0:
animated.play("Normal_Attack")
else:
animated.play("Heavy_Attack")"""
"""Player code
extends CharacterBody2D
@onready var animated = $AnimatedSprite2D
@onready var slash = $SFX/Slash
@onready var power_slash = $SFX/PowerSlash
@onready var double_slash = $SFX/DoubleSlash
@onready var hitbox_na = $Hitbox_NA
@onready var hitbox_ha = $Hitbox_HA
@onready var hitbox_pa = $Hitbox_PA
const SPEED = 300.0
var is_locked: bool = false
var facing_right: bool = true
var is_hurt: bool = false
var knight: Dictionary = {
"atk" : 20,
"hp" : 100,
"def" : 6,
}
var hitboxes: Array
func _ready():
hitboxes = [hitbox_na, hitbox_ha, hitbox_pa]
disable_all_hitboxes()
func _physics_process(_delta) -> void:
if not is_locked and not is_hurt:
process_movement()
attack()
update_hitbox_direction()
animation_hit()
move_and_slide()
func get_current_hitbox() -> Area2D:
if animated.animation == "Normal_Attack":
return hitbox_na
elif animated.animation == "Heavy_Attack":
return hitbox_ha
elif animated.animation == "Power_Attack":
return hitbox_pa
return hitbox_na
func disable_all_hitboxes():
for hitbox in hitboxes:
hitbox.monitoring = false
hitbox.monitorable = false
func process_movement() -> void:
var dir := Input.get_vector("Left", "Right", "Up", "Down")
velocity = dir * SPEED
if dir.x == 0 and dir.y == 0:
animated.play("Idle")
else:
animated.play("Walking")
if dir.x > 0:
facing_right = true
animated.flip_h = false
elif dir.x < 0:
facing_right = false
animated.flip_h = true
func update_hitbox_direction():
for hitbox in hitboxes:
if facing_right:
hitbox.position.x = abs(hitbox.position.x)
else:
hitbox.position.x = -abs(hitbox.position.x)
func start_attack():
is_locked = true
velocity = Vector2.ZERO
disable_all_hitboxes()
func animation_hit():
if is_locked and not is_hurt:
var frame = animated.frame
var hitbox = get_current_hitbox()
if animated.animation == "Normal_Attack":
if frame >= 3 and frame <= 5:
hitbox.monitorable = true
hitbox.monitoring = true
else:
hitbox.monitorable = false
hitbox.monitoring = false
elif animated.animation == "Power_Attack":
if frame >= 6 and frame <= 9:
hitbox.monitorable = true
hitbox.monitoring = true
else:
hitbox.monitorable = false
hitbox.monitoring = false
elif animated.animation == "Heavy_Attack":
if (frame >= 3 and frame <= 5) or (frame >= 7 and frame <= 9):
hitbox.monitorable = true
hitbox.monitoring = true
else:
hitbox.monitorable = false
hitbox.monitoring = false
func attack():
if Input.is_action_just_pressed("Powered_Atk"):
start_attack()
power_slash.play()
animated.play("Power_Attack")
elif Input.is_action_just_pressed("Heavy_Atk"):
start_attack()
double_slash.play()
animated.play("Heavy_Attack")
elif Input.is_action_just_pressed("NA"):
start_attack()
slash.play()
animated.play("Normal_Attack")
func _on_hurtbox_area_entered(area):
if is_hurt or knight["hp"] <= 0:
return
# Process enemy attacks hitting the player body
if area.name == "Hitbox" or area.is_in_group("enemy_hitbox"):
var enemy = area.get_parent()
is_hurt = true
is_locked = false
disable_all_hitboxes()
var incoming_atk = enemy.skeleton["atk"] if "skeleton" in enemy else 10
var total_damage = max(1, incoming_atk - knight["def"])
knight["hp"] -= total_damage
print("Knight took damage! HP left: %d" % knight["hp"])
if knight["hp"] <= 0:
knight["hp"] = 0
animated.play("Death")
else:
animated.play("Hurt")
var knockback_dir = (global_position - enemy.global_position).normalized()
velocity = knockback_dir * 300
func _on_animated_sprite_2d_animation_finished():
if animated.animation == "Death":
return
is_locked = false
is_hurt = false
disable_all_hitboxes()
animated.play("Idle")
"""
