feat: spawn enemies from reusable definitions

This commit is contained in:
Rijad Zuzo
2026-08-12 20:34:55 +02:00
parent 41b37a4962
commit 809e7c008d
12 changed files with 332 additions and 57 deletions
+107
View File
@@ -0,0 +1,107 @@
extends GutTest
func test_core_boar_reuses_wolf_behavior_and_spawns_from_data() -> void:
SimulationEnemies.invalidate_cache()
var wolf := SimulationEnemies.get_enemy(&"enemy_wolf")
var boar := SimulationEnemies.get_enemy(&"enemy_boar")
assert_not_null(wolf)
assert_not_null(boar)
assert_eq(boar.behavior_profile_id, wolf.behavior_profile_id)
assert_eq(boar.behavior_profile_id, EnemyDefinition.BEHAVIOR_PROFILE_WOLF_HUNT)
assert_eq(boar.combatant_id_prefix, "boar")
var factory := CombatantFactory.new()
var combatant := factory.create_enemy(boar.enemy_id, Vector3(1.0, 2.0, 3.0))
assert_not_null(combatant)
assert_eq(combatant.get_combatant_id(), &"boar_0")
assert_eq(combatant.get_enemy_definition_id(), boar.enemy_id)
assert_eq(combatant.get_kind(), boar.kind)
assert_eq(combatant.get_faction_id(), boar.faction_id)
assert_eq(combatant.get_weapon_id(), boar.weapon_id)
assert_eq(combatant.get_max_health(), boar.health)
assert_eq(combatant.is_hostile(), boar.hostile)
func test_factory_accepts_a_definition_without_enemy_specific_code() -> void:
var definition := EnemyDefinition.new()
definition.enemy_id = &"enemy_test_hound"
definition.display_name = "Test Hound"
definition.kind = SimulationIds.COMBATANT_KIND_WOLF
definition.behavior_profile_id = EnemyDefinition.BEHAVIOR_PROFILE_WOLF_HUNT
definition.combatant_id_prefix = "test_hound"
definition.faction_id = SimulationIds.FACTION_TRIBE
definition.hostile = true
definition.weapon_id = SimulationIds.ITEM_CLAW
definition.health = 37.0
var factory := CombatantFactory.new()
assert_true(definition.validate().is_empty())
var combatant := factory.create_from_definition(definition, Vector3.ZERO)
assert_not_null(combatant)
assert_eq(combatant.get_combatant_id(), &"test_hound_0")
assert_eq(combatant.get_enemy_definition_id(), definition.enemy_id)
assert_eq(combatant.get_max_health(), 37.0)
func test_enemy_definition_id_round_trips_and_v1_infers_legacy_ids() -> void:
var current := CombatantStateRecord.create(
&"boar_7",
SimulationIds.COMBATANT_KIND_WOLF,
SimulationIds.FACTION_TRIBE,
"Wild Boar",
Vector3.ZERO,
55.0,
SimulationIds.ITEM_CLAW,
CombatantStateRecord.NO_NPC_ID,
true,
&"enemy_boar"
)
var restored := CombatantStateRecord.from_dictionary(current.to_dictionary())
assert_not_null(restored)
assert_eq(restored.get_enemy_definition_id(), &"enemy_boar")
var legacy_data := current.to_dictionary()
legacy_data["schema_version"] = CombatantStateRecord.LEGACY_SCHEMA_VERSION
legacy_data.erase("enemy_definition_id")
var migrated := CombatantStateRecord.from_dictionary(legacy_data)
assert_not_null(migrated)
assert_eq(migrated.get_enemy_definition_id(), &"enemy_wolf")
assert_eq(int(migrated.to_dictionary()["schema_version"]), CombatantStateRecord.SCHEMA_VERSION)
func test_conflict_restore_rebuilds_collision_free_definition_allocators() -> void:
var records: Array[CombatantStateRecord] = [
_enemy_record(&"wolf_0", &"enemy_wolf"),
_enemy_record(&"wolf_4", &"enemy_wolf"),
_enemy_record(&"boar_2", &"enemy_boar"),
]
var no_factions: Array[FactionStateRecord] = []
var conflict := ConflictSystem.new()
conflict.restore_state_records(records, no_factions, 12)
var wolf_id := conflict.spawn_wolf(Vector3.ZERO)
var boar_id := conflict.spawn_enemy(&"enemy_boar", Vector3.ONE)
assert_eq(wolf_id, &"wolf_5")
assert_eq(boar_id, &"boar_3")
assert_eq(conflict.get_combatant(wolf_id).get_enemy_definition_id(), &"enemy_wolf")
assert_eq(conflict.get_combatant(boar_id).get_enemy_definition_id(), &"enemy_boar")
assert_eq(conflict.get_all_combatants().size(), 6)
func _enemy_record(
combatant_id: StringName, enemy_definition_id: StringName
) -> CombatantStateRecord:
var definition := SimulationEnemies.get_enemy(enemy_definition_id)
return CombatantStateRecord.create(
combatant_id,
definition.kind,
definition.faction_id,
definition.display_name,
Vector3.ZERO,
definition.health,
definition.weapon_id,
CombatantStateRecord.NO_NPC_ID,
definition.hostile,
definition.enemy_id
)