Files
gamedev-the-steward/simulation/conflict/CombatantFactory.gd
T
2026-08-12 20:34:55 +02:00

82 lines
2.3 KiB
GDScript

class_name CombatantFactory
extends RefCounted
var _occupied_ids: Dictionary = {}
var _next_suffix_by_prefix: Dictionary = {}
func reset_allocator() -> void:
_occupied_ids.clear()
_next_suffix_by_prefix.clear()
func restore_allocator(records: Array[CombatantStateRecord]) -> void:
reset_allocator()
for record in records:
if record != null:
reserve_id(record.get_combatant_id())
func reserve_id(combatant_id: StringName) -> bool:
if combatant_id.is_empty() or _occupied_ids.has(combatant_id):
return false
_occupied_ids[combatant_id] = true
_observe_numeric_suffix(combatant_id)
return true
func create_enemy(enemy_definition_id: StringName, position: Vector3) -> CombatantStateRecord:
return create_from_definition(SimulationEnemies.get_enemy(enemy_definition_id), position)
func create_from_definition(definition: EnemyDefinition, position: Vector3) -> CombatantStateRecord:
if definition == null or not definition.validate().is_empty() or not position.is_finite():
return null
var combatant_id := _allocate_id(definition.combatant_id_prefix)
return CombatantStateRecord.create(
combatant_id,
definition.kind,
definition.faction_id,
definition.display_name,
position,
definition.health,
definition.weapon_id,
CombatantStateRecord.NO_NPC_ID,
definition.hostile,
definition.enemy_id
)
func get_next_suffix(prefix: String) -> int:
return int(_next_suffix_by_prefix.get(prefix, 0))
func is_reserved(combatant_id: StringName) -> bool:
return _occupied_ids.has(combatant_id)
func _allocate_id(prefix: String) -> StringName:
var suffix := get_next_suffix(prefix)
var candidate := StringName("%s_%d" % [prefix, suffix])
while _occupied_ids.has(candidate):
suffix += 1
candidate = StringName("%s_%d" % [prefix, suffix])
_occupied_ids[candidate] = true
_next_suffix_by_prefix[prefix] = suffix + 1
return candidate
func _observe_numeric_suffix(combatant_id: StringName) -> void:
var text_id := String(combatant_id)
var separator_index := text_id.rfind("_")
if separator_index <= 0 or separator_index >= text_id.length() - 1:
return
var suffix_text := text_id.substr(separator_index + 1)
if not suffix_text.is_valid_int():
return
var suffix := int(suffix_text)
if suffix < 0:
return
var prefix := text_id.substr(0, separator_index)
_next_suffix_by_prefix[prefix] = maxi(get_next_suffix(prefix), suffix + 1)