feat: spawn enemies from reusable definitions
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
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)
|
||||
Reference in New Issue
Block a user