Files
gamedev-the-steward/simulation/situations/QuestJournalSystem.gd
T

118 lines
3.6 KiB
GDScript

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 definition.get_alternative(alternative_id) == null
or current_tick < situation.get_created_tick()
or _entry_id_by_situation.has(situation.get_situation_id())
or 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 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