Add manual campaign checkpoint saves
This commit is contained in:
@@ -2,6 +2,7 @@ extends RefCounted
|
||||
class_name CampaignState
|
||||
|
||||
const SAVE_PATH := "user://campaign_save.json"
|
||||
const MANUAL_SAVE_PATH := "user://campaign_manual_save.json"
|
||||
const SAVE_VERSION := 3
|
||||
|
||||
var save_version := SAVE_VERSION
|
||||
@@ -151,38 +152,73 @@ func reset_save(scenario_id: String) -> bool:
|
||||
|
||||
|
||||
func load_game() -> bool:
|
||||
if not FileAccess.file_exists(SAVE_PATH):
|
||||
return false
|
||||
|
||||
var parsed = JSON.parse_string(FileAccess.get_file_as_string(SAVE_PATH))
|
||||
if typeof(parsed) != TYPE_DICTIONARY:
|
||||
return false
|
||||
|
||||
save_version = int(parsed.get("save_version", 1))
|
||||
current_scenario_id = str(parsed.get("current_scenario_id", ""))
|
||||
completed_scenarios.clear()
|
||||
for scenario_id in parsed.get("completed_scenarios", []):
|
||||
completed_scenarios.append(str(scenario_id))
|
||||
gold = int(parsed.get("gold", 0))
|
||||
inventory = _copy_dictionary(parsed.get("inventory", {}))
|
||||
roster = _copy_dictionary(parsed.get("roster", {}))
|
||||
flags = _copy_dictionary(parsed.get("flags", {}))
|
||||
applied_post_battle_choices = _copy_dictionary(parsed.get("applied_post_battle_choices", {}))
|
||||
pending_post_battle_choice_scenario_id = str(parsed.get("pending_post_battle_choice_scenario_id", ""))
|
||||
joined_officers.clear()
|
||||
var saved_joined = parsed.get("joined_officers", initial_joined_officers)
|
||||
for officer_id in saved_joined:
|
||||
var normalized := str(officer_id)
|
||||
if normalized.is_empty() or joined_officers.has(normalized):
|
||||
continue
|
||||
joined_officers.append(normalized)
|
||||
return true
|
||||
return _load_game_from_path(SAVE_PATH)
|
||||
|
||||
|
||||
func save_game() -> bool:
|
||||
var file := FileAccess.open(SAVE_PATH, FileAccess.WRITE)
|
||||
return _save_game_to_path(SAVE_PATH)
|
||||
|
||||
|
||||
func has_manual_save() -> bool:
|
||||
return FileAccess.file_exists(MANUAL_SAVE_PATH)
|
||||
|
||||
|
||||
func save_manual_game() -> bool:
|
||||
return _save_game_to_path(MANUAL_SAVE_PATH)
|
||||
|
||||
|
||||
func load_manual_game() -> bool:
|
||||
if not has_manual_save():
|
||||
return false
|
||||
var previous_state := to_dict()
|
||||
if not _load_game_from_path(MANUAL_SAVE_PATH):
|
||||
return false
|
||||
_clear_invalid_pending_post_battle_choice()
|
||||
_normalize_current_scenario()
|
||||
_backfill_applied_post_battle_choices()
|
||||
_reconcile_completed_officer_transitions()
|
||||
if save_game():
|
||||
return true
|
||||
_apply_save_data(previous_state)
|
||||
return false
|
||||
|
||||
|
||||
func get_manual_save_summary() -> Dictionary:
|
||||
if not has_manual_save():
|
||||
return {}
|
||||
var parsed = JSON.parse_string(FileAccess.get_file_as_string(MANUAL_SAVE_PATH))
|
||||
if typeof(parsed) != TYPE_DICTIONARY:
|
||||
return {}
|
||||
var completed_count := 0
|
||||
var completed = parsed.get("completed_scenarios", [])
|
||||
if typeof(completed) == TYPE_ARRAY:
|
||||
completed_count = completed.size()
|
||||
var current_id := str(parsed.get("current_scenario_id", ""))
|
||||
return {
|
||||
"save_version": int(parsed.get("save_version", 1)),
|
||||
"current_scenario_id": current_id,
|
||||
"current_scenario_title": get_scenario_title(current_id),
|
||||
"completed_count": completed_count,
|
||||
"total_count": scenario_order.size(),
|
||||
"gold": int(parsed.get("gold", 0)),
|
||||
"pending_choice": not str(parsed.get("pending_post_battle_choice_scenario_id", "")).is_empty()
|
||||
}
|
||||
|
||||
|
||||
func _load_game_from_path(path: String) -> bool:
|
||||
if not FileAccess.file_exists(path):
|
||||
return false
|
||||
var parsed = JSON.parse_string(FileAccess.get_file_as_string(path))
|
||||
if typeof(parsed) != TYPE_DICTIONARY:
|
||||
return false
|
||||
_apply_save_data(parsed)
|
||||
return true
|
||||
|
||||
|
||||
func _save_game_to_path(path: String) -> bool:
|
||||
var file := FileAccess.open(path, FileAccess.WRITE)
|
||||
if file == null:
|
||||
push_error("Unable to save campaign state: %s" % SAVE_PATH)
|
||||
push_error("Unable to save campaign state: %s" % path)
|
||||
return false
|
||||
file.store_string(JSON.stringify(to_dict()))
|
||||
return true
|
||||
@@ -202,8 +238,8 @@ func apply_battle_result(battle_state) -> Dictionary:
|
||||
}
|
||||
|
||||
var already_completed := completed_scenarios.has(battle_state.battle_id)
|
||||
var rewards := battle_state.get_rewards()
|
||||
var post_battle_choices := battle_state.get_post_battle_choices()
|
||||
var rewards: Dictionary = battle_state.get_rewards()
|
||||
var post_battle_choices: Array = battle_state.get_post_battle_choices()
|
||||
if already_completed:
|
||||
var return_scenario_id := current_scenario_id if not is_campaign_complete() else ""
|
||||
return {
|
||||
@@ -678,7 +714,7 @@ func get_chapter_progress_entries() -> Array:
|
||||
var scenarios := []
|
||||
for scenario_id in scenario_ids:
|
||||
var completed := completed_scenarios.has(scenario_id)
|
||||
var current := scenario_id == current_scenario_id
|
||||
var current: bool = scenario_id == current_scenario_id
|
||||
if completed_scenarios.has(scenario_id):
|
||||
completed_count += 1
|
||||
if current:
|
||||
@@ -763,6 +799,27 @@ func to_dict() -> Dictionary:
|
||||
}
|
||||
|
||||
|
||||
func _apply_save_data(parsed: Dictionary) -> void:
|
||||
save_version = int(parsed.get("save_version", 1))
|
||||
current_scenario_id = str(parsed.get("current_scenario_id", ""))
|
||||
completed_scenarios.clear()
|
||||
for scenario_id in parsed.get("completed_scenarios", []):
|
||||
completed_scenarios.append(str(scenario_id))
|
||||
gold = int(parsed.get("gold", 0))
|
||||
inventory = _copy_dictionary(parsed.get("inventory", {}))
|
||||
roster = _copy_dictionary(parsed.get("roster", {}))
|
||||
flags = _copy_dictionary(parsed.get("flags", {}))
|
||||
applied_post_battle_choices = _copy_dictionary(parsed.get("applied_post_battle_choices", {}))
|
||||
pending_post_battle_choice_scenario_id = str(parsed.get("pending_post_battle_choice_scenario_id", ""))
|
||||
joined_officers.clear()
|
||||
var saved_joined = parsed.get("joined_officers", initial_joined_officers)
|
||||
for officer_id in saved_joined:
|
||||
var normalized := str(officer_id)
|
||||
if normalized.is_empty() or joined_officers.has(normalized):
|
||||
continue
|
||||
joined_officers.append(normalized)
|
||||
|
||||
|
||||
func _copy_dictionary(value) -> Dictionary:
|
||||
if typeof(value) == TYPE_DICTIONARY:
|
||||
return value.duplicate(true)
|
||||
|
||||
Reference in New Issue
Block a user