diff --git a/scenes/game_elements/props/filling_barrel/components/fragile_barrel.gd b/scenes/game_elements/props/filling_barrel/components/fragile_barrel.gd index 82b8b348fc..6527678605 100644 --- a/scenes/game_elements/props/filling_barrel/components/fragile_barrel.gd +++ b/scenes/game_elements/props/filling_barrel/components/fragile_barrel.gd @@ -7,50 +7,38 @@ extends FillingBarrel ## Emitted when [member current_health] reaches 0. signal barrel_destroyed(barrel_instance: FragileBarrel) -## Maximum hits the barrel can take before breaking. -@export_range(1, 100) var max_health: int = 4 - -var current_health: int - @onready var crack_overlay_node: AnimatedSprite2D = %CrackOverlay @onready var crack_sound: AudioStreamPlayer2D = %CrackSound @onready var shatter_sound: AudioStreamPlayer2D = %ShatterSound +@onready var health_component: HealthComponent = %HealthComponent func _ready() -> void: super._ready() - current_health = max_health crack_overlay_node.visible = false # Logic called by Projectile when it hits this object func hit_by_droplet(droplet_label: String) -> void: # Ignore if already full or destroyed - if _amount >= needed_amount or current_health <= 0: + if _amount >= needed_amount or health_component.has_depleted_health: return if droplet_label == self.label: increment() else: - take_damage() + health_component.damage(1) func take_damage() -> void: - current_health -= 1 - - if current_health <= 0: - break_barrel() - else: - crack_sound.play() - update_cracks() + crack_sound.play() + update_cracks() func update_cracks() -> void: - var damage_taken: int = max_health - current_health - # IMPROVEMENT: Calculate frame index proportionally based on damage percentage. var total_frames: int = crack_overlay_node.sprite_frames.get_frame_count("default") - var frame_index: int = int(floor((float(damage_taken) / max_health) * total_frames)) + var frame_index: int = int(floor((health_component.damage_taken_percentage) * total_frames)) # Clamp to ensure we don't exceed available frames (0-based index) frame_index = clamp(frame_index, 0, total_frames - 1) diff --git a/scenes/game_elements/props/filling_barrel/fragile_barrel.tscn b/scenes/game_elements/props/filling_barrel/fragile_barrel.tscn index 9ec6d67807..068b803480 100644 --- a/scenes/game_elements/props/filling_barrel/fragile_barrel.tscn +++ b/scenes/game_elements/props/filling_barrel/fragile_barrel.tscn @@ -5,10 +5,10 @@ [ext_resource type="Script" uid="uid://d05hp7ascndlr" path="res://scenes/game_elements/props/filling_barrel/components/fragile_barrel.gd" id="2_wal8y"] [ext_resource type="AudioStream" uid="uid://bknpb07lvbded" path="res://scenes/game_elements/props/filling_barrel/components/sfx_barrel_crack.tres" id="4_sdj6j"] [ext_resource type="AudioStream" uid="uid://c3iuv5ax8i78v" path="res://scenes/game_elements/props/filling_barrel/components/sfx_barrel_breaking.tres" id="5_v7k7g"] +[ext_resource type="Script" uid="uid://b0qrfv6upnqtu" path="res://scenes/game_logic/health_component.gd" id="6_v7k7g"] [node name="FragileBarrel" unique_id=2064522120 instance=ExtResource("1_ab25j")] script = ExtResource("2_wal8y") -max_health = 4 [node name="CrackOverlay" type="AnimatedSprite2D" parent="." index="1" unique_id=473951260] unique_name_in_owner = true @@ -25,3 +25,11 @@ bus = &"SFX" unique_name_in_owner = true stream = ExtResource("5_v7k7g") bus = &"SFX" + +[node name="HealthComponent" type="Node2D" parent="." index="10" unique_id=1654759649] +unique_name_in_owner = true +script = ExtResource("6_v7k7g") +metadata/_custom_type_script = "uid://b0qrfv6upnqtu" + +[connection signal="health_changed" from="HealthComponent" to="." method="take_damage" unbinds=1] +[connection signal="health_depleted" from="HealthComponent" to="." method="break_barrel"] diff --git a/scenes/game_logic/health_component.gd b/scenes/game_logic/health_component.gd new file mode 100644 index 0000000000..feb924f673 --- /dev/null +++ b/scenes/game_logic/health_component.gd @@ -0,0 +1,40 @@ +# SPDX-FileCopyrightText: The Threadbare Authors +# SPDX-License-Identifier: MPL-2.0 +class_name HealthComponent +extends Node2D + +signal health_depleted +signal health_changed(current_health: int) + +@export_range(1, 100) var max_health: int = 4 + +var current_health: int = max_health: + set(value): + if value == current_health: + pass + + current_health = value + if current_health <= 0: + health_depleted.emit() + else: + health_changed.emit(current_health) + +var damage_taken: int: + get: + return max_health - current_health + +var damage_taken_percentage: float: + get: + return float(damage_taken) / max_health + +var has_depleted_health: bool: + get: + return current_health <= 0 + + +func damage(amount: int) -> void: + current_health -= amount + + +func heal(amount: int) -> void: + current_health += amount diff --git a/scenes/game_logic/health_component.gd.uid b/scenes/game_logic/health_component.gd.uid new file mode 100644 index 0000000000..4c03ccc366 --- /dev/null +++ b/scenes/game_logic/health_component.gd.uid @@ -0,0 +1 @@ +uid://b0qrfv6upnqtu