newlon/scripts/entities/entity.gd
2025-08-09 21:35:02 +05:00

108 lines
2.5 KiB
GDScript

extends Node
## Base class for all hp-based objects
class_name Entity
## Maximum health points of an entity. Any heal cannot exceed this value
@export var max_hp : float
## Optional spawn layer for grid interactions
@export var layer : StringName = ""
## Current amount of health points of an entity. Cannot be below 0 or [code]max_hp[/code]
@onready var hp : float = max_hp
##
var disabled : bool = false
signal damaged
## Emitted when damage is taken
signal damage_taken(context : DamageTakenContext)
## Emitted when entity is healed
signal healed(context : HealedContext)
## Emitted on every health points change
signal hp_changed(context : HPChangedContext)
## Emitted when kill is requested
signal killed(context : KilledContext)
##
signal toggled(disabled : bool)
##
func disable():
if disabled: return
disabled = true
toggled.emit(disabled)
##
func enable():
if disabled == false: return
disabled = false
toggled.emit(disabled)
## Properly deal damage to entity
func deal_damage(amount : float, source : Entity):
var context = DamageTakenContext.new()
context.source = source
context.target = self
context.amount = amount
damage_taken.emit(context)
var delta_context = HPChangedContext.new()
delta_context.source = source
delta_context.target = self
delta_context.delta = -amount
hp_changed.emit(delta_context)
damaged.emit()
hp -= amount
if hp <= 0:
hp = 0
kill(source)
## Properly heal entity
func heal(amount : float, source : Entity):
var context = HealedContext.new()
context.source = source
context.target = self
context.amount = amount
healed.emit(context)
var delta_context = HPChangedContext.new()
delta_context.source = source
delta_context.target = self
delta_context.delta = amount
hp_changed.emit(delta_context)
hp += amount
if hp > max_hp:
hp = max_hp
## Invoked when an entity is killed by damage.
func kill(source : Entity):
var context = KilledContext.new()
context.source = source
context.target = self
killed.emit(context)
LevelEventBus.entity_killed.emit(context)
if not layer.is_empty():
LevelEventBus.layer_entity_killed.emit(context)
## Method used to properly deconstruct entity
func deconstruct():
queue_free()
class DamageTakenContext:
var target : Entity
var source : Entity
var amount : float
class HealedContext:
var target : Entity
var source : Entity
var amount : float
class KilledContext:
var target : Entity
var source : Entity
class HPChangedContext:
var target : Entity
var source : Entity
var delta : float