82 lines
2.3 KiB
GDScript
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)
|