class_name QuestJournalSystem extends RefCounted var _entries_by_id: Dictionary = {} var _entry_id_by_situation: Dictionary = {} var _next_entry_id := 0 func add_situation( situation: SituationStateRecord, definition: SituationDefinition, alternative_id: StringName, current_tick: int ) -> QuestJournalEntryStateRecord: if ( situation == null or definition == null or not situation.is_active() or situation.get_definition_id() != definition.situation_definition_id or (not alternative_id.is_empty() and definition.get_alternative(alternative_id) == null) or current_tick < situation.get_created_tick() or _entry_id_by_situation.has(situation.get_situation_id()) ): return null if not alternative_id.is_empty() and not situation.select_alternative(alternative_id): return null var entry := QuestJournalEntryStateRecord.create( _next_entry_id, situation.get_situation_id(), definition.situation_definition_id, current_tick, alternative_id ) _entries_by_id[_next_entry_id] = entry _entry_id_by_situation[situation.get_situation_id()] = _next_entry_id _next_entry_id += 1 return entry func select_alternative( situation: SituationStateRecord, definition: SituationDefinition, alternative_id: StringName ) -> bool: if ( situation == null or definition == null or alternative_id.is_empty() or situation.get_definition_id() != definition.situation_definition_id or definition.get_alternative(alternative_id) == null ): return false var entry := get_for_situation(situation.get_situation_id()) if entry == null or not entry.is_active(): return false return situation.select_alternative(alternative_id) and entry.select_alternative(alternative_id) func synchronize( situation: SituationStateRecord, current_tick: int ) -> QuestJournalEntryStateRecord: if situation == null: return null var entry := get_for_situation(situation.get_situation_id()) if entry == null or not entry.is_active() or situation.is_active(): return null var status := QuestJournalEntryStateRecord.STATUS_ARCHIVED if situation.get_status() == SituationStateRecord.STATUS_RESOLVED: status = QuestJournalEntryStateRecord.STATUS_COMPLETED elif situation.get_status() == SituationStateRecord.STATUS_EXPIRED: status = QuestJournalEntryStateRecord.STATUS_FAILED return entry if entry.close(status, current_tick) else null func derive_progress( entry: QuestJournalEntryStateRecord, situation_system: SituationSystem, world_events: WorldEventStore, state_facts: Dictionary ) -> SituationProgressSnapshot: if entry == null or situation_system == null: return SituationProgressSnapshot.new() return situation_system.derive_progress( situation_system.get_by_id(entry.get_situation_id()), world_events, state_facts, entry.get_selected_alternative_id() ) func restore(records: Array[QuestJournalEntryStateRecord], restored_next_id: int) -> bool: var by_id: Dictionary = {} var by_situation: Dictionary = {} var next_id := maxi(restored_next_id, 0) for record in records: if ( record == null or by_id.has(record.get_entry_id()) or by_situation.has(record.get_situation_id()) ): return false by_id[record.get_entry_id()] = record by_situation[record.get_situation_id()] = record.get_entry_id() next_id = maxi(next_id, record.get_entry_id() + 1) _entries_by_id = by_id _entry_id_by_situation = by_situation _next_entry_id = next_id return true func get_by_id(entry_id: int) -> QuestJournalEntryStateRecord: return _entries_by_id.get(entry_id) as QuestJournalEntryStateRecord func get_for_situation(situation_id: int) -> QuestJournalEntryStateRecord: if not _entry_id_by_situation.has(situation_id): return null return get_by_id(int(_entry_id_by_situation[situation_id])) func get_all_sorted() -> Array[QuestJournalEntryStateRecord]: var records: Array[QuestJournalEntryStateRecord] = [] for record in _entries_by_id.values(): records.append(record) records.sort_custom( func(first: QuestJournalEntryStateRecord, second: QuestJournalEntryStateRecord) -> bool: return first.get_entry_id() < second.get_entry_id() ) return records func get_active_sorted() -> Array[QuestJournalEntryStateRecord]: var records: Array[QuestJournalEntryStateRecord] = [] for record in get_all_sorted(): if record.is_active(): records.append(record) return records func get_next_entry_id() -> int: return _next_entry_id