class_name QuestJournalEntryStateRecord extends RefCounted const SCHEMA_VERSION := 1 const STATUS_ACTIVE := &"active" const STATUS_COMPLETED := &"completed" const STATUS_FAILED := &"failed" const STATUS_ARCHIVED := &"archived" const VALID_STATUSES := [STATUS_ACTIVE, STATUS_COMPLETED, STATUS_FAILED, STATUS_ARCHIVED] const TRACKING_AUTO := &"auto" const TRACKING_TRACKED := &"tracked" const TRACKING_UNTRACKED := &"untracked" const VALID_TRACKING_PREFERENCES := [TRACKING_AUTO, TRACKING_TRACKED, TRACKING_UNTRACKED] var data: Dictionary func _init(record_data: Dictionary = {}) -> void: data = record_data.duplicate(true) static func create( entry_id: int, situation_id: int, definition_id: StringName, discovered_tick: int, selected_alternative_id: StringName = &"", tracking_preference: StringName = TRACKING_AUTO ) -> QuestJournalEntryStateRecord: if ( entry_id < 0 or situation_id < 0 or definition_id.is_empty() or discovered_tick < 0 or tracking_preference not in VALID_TRACKING_PREFERENCES ): return null return ( QuestJournalEntryStateRecord . new( { "schema_version": SCHEMA_VERSION, "entry_id": entry_id, "situation_id": situation_id, "definition_id": String(definition_id), "status": String(STATUS_ACTIVE), "discovered_tick": discovered_tick, "selected_alternative_id": String(selected_alternative_id), "tracking_preference": String(tracking_preference), "closed_tick": -1, } ) ) static func from_dictionary(record_data: Dictionary) -> QuestJournalEntryStateRecord: if int(record_data.get("schema_version", -1)) != SCHEMA_VERSION: return null if not ( record_data . has_all( [ "entry_id", "situation_id", "definition_id", "status", "discovered_tick", "selected_alternative_id", "tracking_preference", "closed_tick", ] ) ): return null var entry_id := int(record_data["entry_id"]) var situation_id := int(record_data["situation_id"]) var definition_id := StringName(record_data["definition_id"]) var status := StringName(record_data["status"]) var discovered_tick := int(record_data["discovered_tick"]) var selected_alternative_id := StringName(record_data["selected_alternative_id"]) var tracking_preference := StringName(record_data["tracking_preference"]) var closed_tick := int(record_data["closed_tick"]) if ( entry_id < 0 or situation_id < 0 or definition_id.is_empty() or status not in VALID_STATUSES or discovered_tick < 0 or tracking_preference not in VALID_TRACKING_PREFERENCES ): return null if ( (status == STATUS_ACTIVE and closed_tick != -1) or (status != STATUS_ACTIVE and closed_tick < discovered_tick) ): return null var record := create( entry_id, situation_id, definition_id, discovered_tick, selected_alternative_id, tracking_preference ) if status != STATUS_ACTIVE: record.close(status, closed_tick) return record func get_entry_id() -> int: return int(data["entry_id"]) func get_situation_id() -> int: return int(data["situation_id"]) func get_definition_id() -> StringName: return StringName(data["definition_id"]) func get_status() -> StringName: return StringName(data["status"]) func get_discovered_tick() -> int: return int(data["discovered_tick"]) func get_selected_alternative_id() -> StringName: return StringName(data["selected_alternative_id"]) func get_tracking_preference() -> StringName: return StringName(data["tracking_preference"]) func get_closed_tick() -> int: return int(data["closed_tick"]) func is_active() -> bool: return get_status() == STATUS_ACTIVE func is_archived() -> bool: return get_status() == STATUS_ARCHIVED func set_tracking_preference(preference: StringName) -> bool: if preference not in VALID_TRACKING_PREFERENCES: return false data["tracking_preference"] = String(preference) return true func select_alternative(alternative_id: StringName) -> bool: if not is_active() or alternative_id.is_empty(): return false var selected := get_selected_alternative_id() if not selected.is_empty() and selected != alternative_id: return false data["selected_alternative_id"] = String(alternative_id) return true func archive(closed_tick: int) -> bool: return close(STATUS_ARCHIVED, closed_tick) func close(status: StringName, closed_tick: int) -> bool: if ( not is_active() or status not in [STATUS_COMPLETED, STATUS_FAILED, STATUS_ARCHIVED] or closed_tick < get_discovered_tick() ): return false data["status"] = String(status) data["closed_tick"] = closed_tick return true func to_dictionary() -> Dictionary: return data.duplicate(true)