extends Node2D # Sword Slash - Swings around player and deals damage @export var damage: float = 20.0 @export var swing_speed: float = 720.0 # Degrees per second @export var swing_radius: float = 40.0 # Distance from player center (closer swing) @export var lifetime: float = 0.3 # How long the slash lasts var swing_angle: float = 0.0 # Current angle var swing_start_angle: float = 0.0 # Starting angle var swing_arc: float = 180.0 # Total arc to swing (180 degrees) var elapsed_time: float = 0.0 var player_owner: Node = null var hit_targets = {} # Track what we've already hit (Dictionary for O(1) lookup) @onready var sprite = $Sprite2D @onready var hit_area = $Area2D func _ready(): # Connect area signals if hit_area: hit_area.body_entered.connect(_on_body_entered) # Set initial rotation rotation = deg_to_rad(swing_start_angle) func setup(start_angle: float, owner_player: Node, arc_direction: float = 1.0): swing_start_angle = start_angle swing_angle = start_angle player_owner = owner_player swing_arc = 180.0 * arc_direction # Positive or negative arc rotation = deg_to_rad(swing_start_angle) func _physics_process(delta): elapsed_time += delta # Check lifetime if elapsed_time >= lifetime: queue_free() return # Calculate swing progress (0 to 1) var progress = elapsed_time / lifetime # Swing the sword in an arc swing_angle = swing_start_angle + (swing_arc * progress) rotation = deg_to_rad(swing_angle) # Position around player if we have one if player_owner and is_instance_valid(player_owner): var offset = Vector2(swing_radius, 0).rotated(deg_to_rad(swing_angle)) global_position = player_owner.global_position + offset func _on_body_entered(body): # Don't hit the owner if body == player_owner: return # Don't hit the same target twice - use Dictionary for O(1) lookup to prevent race conditions if body in hit_targets: return # Add to hit_targets IMMEDIATELY to prevent multiple hits (mark as hit before processing) hit_targets[body] = true # Deal damage to players if body.is_in_group("player") and body.has_method("take_damage"): body.take_damage(damage, global_position) print("Sword hit player: ", body.name, " for ", damage, " damage!") # Deal damage to boxes or other damageable objects elif "health" in body: # Boxes have health property body.health -= damage if body.health <= 0 and body.has_method("_break_into_pieces"): body._break_into_pieces() print("Sword hit object: ", body.name) # Push the hit target away slightly if body is CharacterBody2D: var knockback_dir = (body.global_position - global_position).normalized() body.velocity = knockback_dir * 200.0