class_name Creature extends CharacterBody2D ## Emitted when the creature is damaged signal damaged(amount: int) ## Emitted when the creature is healed signal healed(amount: int) ## Emitted when the creature dies signal death ## Emitted when a status effect is applied to the creature signal status_effect_applied(effect: StatusEffect) ## Emitted when a status effect is removed from the creature signal status_effect_removed(effect: StatusEffect) @export_category("Creature") ## The creature's maximum health @export var max_hp: int = 1 ## The sound to play when the creature dies @export var death_sound: AudioStream = null ## If true, the creature will be freed when it dies @export var free_on_death: bool = true @export var uses_gravity: bool = true ## The creature's current health var hp: int: get: return hp set(value): var old_hp = hp hp = clampi(value, 0, max_hp) if hp < old_hp: self.damaged.emit(old_hp - hp) elif hp > old_hp: self.healed.emit(hp - old_hp) if hp == 0: self.death.emit() var _status_effects: Array = [] @onready var default_gravity: float = ProjectSettings.get_setting("physics/2d/default_gravity") func _ready() -> void: self.hp = self.max_hp self.death.connect(self._creature_on_death) if self.has_method("_on_ready"): self.call("_on_ready") func _physics_process(delta: float) -> void: if self.uses_gravity: self.velocity.y += self.default_gravity * delta if self.is_on_floor(): self.velocity.y = 0 self.move_and_slide() func _process(delta: float) -> void: for status_effect in self._status_effects: status_effect.process(self, delta) ## Damage the creature by the given amount func take_damage(damage: int) -> void: self.hp -= damage ## Heal the creature by the given amount func heal(amount: int) -> void: self.hp += amount ## Callback for when the creature dies func _creature_on_death() -> void: # Play a sound on creature death if self.death_sound: var audio_player = AudioStreamPlayer2D.new() self.get_parent().add_child(audio_player) audio_player.stream = self.death_sound audio_player.bus = "Sound Effects" audio_player.finished.connect(audio_player.queue_free) audio_player.play() # Destroy on death if self.free_on_death: self.queue_free() ## Returns true if the creature's health is greater than 0 func is_alive() -> bool: return hp > 0 ## Reset the creature's health to its maximum func reset_health() -> void: self.hp = self.max_hp ## Apply a status effect to the creature func apply_status_effect(status_effect: StatusEffect) -> void: status_effect.apply(self) ## Remove a status effect from the creature func remove_status_effect(status_effect: StatusEffect) -> void: status_effect.remove(self) self._status_effects.erase(status_effect) ## Remove all status effects from the creature func clear_status_effects() -> void: for status_effect in self._status_effects: self.remove_status_effect(status_effect)