feat: define reusable animal archetypes

This commit is contained in:
Rijad Zuzo
2026-08-12 20:50:52 +02:00
parent d5eb2b81f9
commit 4e4ae1a969
20 changed files with 1141 additions and 411 deletions
+56 -3
View File
@@ -9,10 +9,13 @@ signal routine_arrived(animal_id: StringName, site_id: StringName, arrival_posit
signal navigation_failed(animal_id: StringName, site_id: StringName)
static var _all: Array[AnimalNode] = []
static var _core_animal_catalog: AnimalCatalog
@export var animal_id: StringName
@export var display_name := "Animal"
@export var species_id: StringName = SimulationIds.SPECIES_GOAT
@export var animal_definition_id: StringName
@export var species_id: StringName
@export var supported_action_ids: Array[StringName] = []
@export_range(0.0, 100.0, 0.5) var initial_hunger := 70.0
@export var initial_enabled := true
@export var can_npcs_feed := true
@@ -35,9 +38,20 @@ var navigation_target := Vector3.INF
var navigation_request_id := 0
var path_pending := false
var has_reported_navigation_result := true
var _animal_definition: AnimalDefinition
func _ready() -> void:
if not _ensure_animal_definition():
push_error(
(
"AnimalNode at %s has invalid animal_definition_id '%s'"
% [get_path(), animal_definition_id]
)
)
initial_enabled = false
_update_presentation()
return
if animal_id.is_empty():
push_error("AnimalNode at %s has empty animal_id" % get_path())
initial_enabled = false
@@ -69,7 +83,11 @@ func _exit_tree() -> void:
func bind_state(animal_state: AnimalStateRecord) -> bool:
if animal_state == null or animal_state.get_animal_id() != animal_id:
if (
animal_state == null
or animal_state.get_animal_id() != animal_id
or animal_state.get_animal_definition_id() != animal_definition_id
):
return false
_disconnect_state()
state = animal_state
@@ -111,7 +129,42 @@ func get_interaction_position() -> Vector3:
func supports_action(action_id: StringName) -> bool:
return action_id == SimulationIds.ACTION_FEED_ANIMAL
return action_id in supported_action_ids
func apply_animal_definition(definition: AnimalDefinition) -> bool:
if definition == null or not definition.validate().is_empty():
return false
if state != null and state.get_animal_definition_id() != definition.animal_definition_id:
return false
_animal_definition = definition
animal_definition_id = definition.animal_definition_id
species_id = definition.species_id
supported_action_ids = definition.supported_action_ids.duplicate()
move_speed = definition.movement_speed
var visual := get_node_or_null("Visual")
if visual != null and visual.has_method("apply_animal_definition"):
return bool(visual.apply_animal_definition(definition))
return true
func get_animal_definition() -> AnimalDefinition:
return _animal_definition
func _ensure_animal_definition() -> bool:
if (
_animal_definition != null
and _animal_definition.animal_definition_id == animal_definition_id
):
return true
if animal_definition_id.is_empty():
return false
if _core_animal_catalog == null:
_core_animal_catalog = AnimalCatalog.create_core()
if _core_animal_catalog == null:
return false
return apply_animal_definition(_core_animal_catalog.get_definition(animal_definition_id))
func get_hunger() -> float: