mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-06 06:01:46 +00:00
Rewrote save game screen, added rest of multiple save file support
This commit is contained in:
@@ -8,16 +8,10 @@
|
|||||||
module SaveData
|
module SaveData
|
||||||
DIRECTORY = (File.directory?(System.data_directory)) ? System.data_directory : "./"
|
DIRECTORY = (File.directory?(System.data_directory)) ? System.data_directory : "./"
|
||||||
FILENAME_REGEX = /Game(\d*)\.rxdata$/
|
FILENAME_REGEX = /Game(\d*)\.rxdata$/
|
||||||
# Contains the file path of the save file.
|
|
||||||
FILE_PATH = if File.directory?(System.data_directory)
|
|
||||||
System.data_directory + "/Game.rxdata"
|
|
||||||
else
|
|
||||||
"./Game.rxdata"
|
|
||||||
end
|
|
||||||
|
|
||||||
# @return [Boolean] whether the save file exists
|
# @return [Boolean] whether any save files exist
|
||||||
def self.exists?
|
def self.exists?
|
||||||
return File.file?(FILE_PATH)
|
return !all_save_files.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return[Array] array of filenames in the save folder that are save files
|
# @return[Array] array of filenames in the save folder that are save files
|
||||||
@@ -60,7 +54,7 @@ module SaveData
|
|||||||
def self.read_from_file(file_path)
|
def self.read_from_file(file_path)
|
||||||
validate file_path => String
|
validate file_path => String
|
||||||
save_data = get_data_from_file(file_path)
|
save_data = get_data_from_file(file_path)
|
||||||
save_data = to_hash_format(save_data) if save_data.is_a?(Array)
|
save_data = to_hash_format(save_data) if save_data.is_a?(Array) # Pre-v19 save file support
|
||||||
if !save_data.empty? && run_conversions(save_data)
|
if !save_data.empty? && run_conversions(save_data)
|
||||||
File.open(file_path, "wb") { |file| Marshal.dump(save_data, file) }
|
File.open(file_path, "wb") { |file| Marshal.dump(save_data, file) }
|
||||||
end
|
end
|
||||||
@@ -84,6 +78,11 @@ module SaveData
|
|||||||
File.delete(DIRECTORY + filename + ".bak") if File.file?(DIRECTORY + filename + ".bak")
|
File.delete(DIRECTORY + filename + ".bak") if File.file?(DIRECTORY + filename + ".bak")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.filename_from_index(index = 0)
|
||||||
|
return "Game.rxdata" if index <= 0
|
||||||
|
return "Game#{index}.rxdata"
|
||||||
|
end
|
||||||
|
|
||||||
# Converts the pre-v19 format data to the new format.
|
# Converts the pre-v19 format data to the new format.
|
||||||
# @param old_format [Array] pre-v19 format save data
|
# @param old_format [Array] pre-v19 format save data
|
||||||
# @return [Hash] save data in new format
|
# @return [Hash] save data in new format
|
||||||
|
|||||||
@@ -201,7 +201,8 @@ module SaveData
|
|||||||
validate save_data => Hash
|
validate save_data => Hash
|
||||||
conversions_to_run = self.get_conversions(save_data)
|
conversions_to_run = self.get_conversions(save_data)
|
||||||
return false if conversions_to_run.none?
|
return false if conversions_to_run.none?
|
||||||
File.open(SaveData::FILE_PATH + ".bak", "wb") { |f| Marshal.dump(save_data, f) }
|
filepath = SaveData::DIRECTORY + SaveData.filename_from_index(save_data[:stats].save_filename_number || 0)
|
||||||
|
File.open(filepath + ".bak", "wb") { |f| Marshal.dump(save_data, f) }
|
||||||
Console.echo_h1(_INTL("Converting save file"))
|
Console.echo_h1(_INTL("Converting save file"))
|
||||||
conversions_to_run.each do |conversion|
|
conversions_to_run.each do |conversion|
|
||||||
Console.echo_li("#{conversion.title}...")
|
Console.echo_li("#{conversion.title}...")
|
||||||
|
|||||||
@@ -27,9 +27,7 @@ module Game
|
|||||||
pbSetResizeFactor([$PokemonSystem.screensize, 4].min)
|
pbSetResizeFactor([$PokemonSystem.screensize, 4].min)
|
||||||
# Set language (and choose language if there is no save file)
|
# Set language (and choose language if there is no save file)
|
||||||
if !Settings::LANGUAGES.empty?
|
if !Settings::LANGUAGES.empty?
|
||||||
# TODO: Change this to check for any save file.
|
$PokemonSystem.language = pbChooseLanguage if !SaveData.exists? && Settings::LANGUAGES.length >= 2
|
||||||
save_data = (SaveData.exists?) ? SaveData.read_from_file(SaveData::FILE_PATH) : {}
|
|
||||||
$PokemonSystem.language = pbChooseLanguage if save_data.empty? && Settings::LANGUAGES.length >= 2
|
|
||||||
MessageTypes.load_message_files(Settings::LANGUAGES[$PokemonSystem.language][1])
|
MessageTypes.load_message_files(Settings::LANGUAGES[$PokemonSystem.language][1])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -41,7 +39,6 @@ module Game
|
|||||||
$game_map.events.each_value { |event| event.clear_starting }
|
$game_map.events.each_value { |event| event.clear_starting }
|
||||||
end
|
end
|
||||||
$game_temp.common_event_id = 0 if $game_temp
|
$game_temp.common_event_id = 0 if $game_temp
|
||||||
$game_temp.begun_new_game = true
|
|
||||||
pbMapInterpreter&.clear
|
pbMapInterpreter&.clear
|
||||||
pbMapInterpreter&.setup(nil, 0, 0)
|
pbMapInterpreter&.setup(nil, 0, 0)
|
||||||
$scene = Scene_Map.new
|
$scene = Scene_Map.new
|
||||||
@@ -104,18 +101,21 @@ module Game
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Saves the game. Returns whether the operation was successful.
|
# Saves the game. Returns whether the operation was successful.
|
||||||
# @param save_file [String] the save file path
|
# @param index [Integer] the number to put in the save file's name Game#.rzdata
|
||||||
|
# @param directory [String] the folder to put the save file in
|
||||||
# @param safe [Boolean] whether $PokemonGlobal.safesave should be set to true
|
# @param safe [Boolean] whether $PokemonGlobal.safesave should be set to true
|
||||||
# @return [Boolean] whether the operation was successful
|
# @return [Boolean] whether the operation was successful
|
||||||
# @raise [SaveData::InvalidValueError] if an invalid value is being saved
|
# @raise [SaveData::InvalidValueError] if an invalid value is being saved
|
||||||
def save(save_file = SaveData::FILE_PATH, safe: false)
|
def save(index, directory = SaveData::DIRECTORY, safe: false)
|
||||||
validate save_file => String, safe => [TrueClass, FalseClass]
|
validate index => Integer, directory => String, safe => [TrueClass, FalseClass]
|
||||||
|
filename = SaveData.filename_from_index(index)
|
||||||
$PokemonGlobal.safesave = safe
|
$PokemonGlobal.safesave = safe
|
||||||
$game_system.save_count += 1
|
$game_system.save_count += 1
|
||||||
$game_system.magic_number = $data_system.magic_number
|
$game_system.magic_number = $data_system.magic_number
|
||||||
$stats.set_time_last_saved
|
$stats.set_time_last_saved
|
||||||
|
$stats.save_filename_number = index
|
||||||
begin
|
begin
|
||||||
SaveData.save_to_file(save_file)
|
SaveData.save_to_file(directory + filename)
|
||||||
Graphics.frame_reset
|
Graphics.frame_reset
|
||||||
rescue IOError, SystemCallError
|
rescue IOError, SystemCallError
|
||||||
$game_system.save_count -= 1
|
$game_system.save_count -= 1
|
||||||
|
|||||||
@@ -1153,9 +1153,7 @@ class Interpreter
|
|||||||
# * Call Save Screen
|
# * Call Save Screen
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
def command_352
|
def command_352
|
||||||
scene = PokemonSave_Scene.new
|
pbFadeOutIn { UI::Save.new.main }
|
||||||
screen = PokemonSaveScreen.new(scene)
|
|
||||||
screen.pbSaveScreen
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
8
Data/Scripts/003_New_UI_Settings.rb
Normal file
8
Data/Scripts/003_New_UI_Settings.rb
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#===============================================================================
|
||||||
|
# NOTE: Some Settings in here will be moved elsewhere eventually. They're all
|
||||||
|
# just gathered here while the new UI is being written.
|
||||||
|
#===============================================================================
|
||||||
|
module Settings
|
||||||
|
# :one, :adventure, :multiple
|
||||||
|
SAVE_SLOTS = :multiple
|
||||||
|
end
|
||||||
@@ -41,7 +41,6 @@ class Game_Temp
|
|||||||
attr_accessor :background_bitmap
|
attr_accessor :background_bitmap
|
||||||
attr_accessor :fadestate # for sprite hashes
|
attr_accessor :fadestate # for sprite hashes
|
||||||
# Other
|
# Other
|
||||||
attr_accessor :begun_new_game # new game flag (true fron new game until saving)
|
|
||||||
attr_accessor :menu_beep # menu: play sound effect flag
|
attr_accessor :menu_beep # menu: play sound effect flag
|
||||||
attr_accessor :menu_last_choice # pause menu: index of last selection
|
attr_accessor :menu_last_choice # pause menu: index of last selection
|
||||||
attr_accessor :memorized_bgm # set when trainer intro BGM is played
|
attr_accessor :memorized_bgm # set when trainer intro BGM is played
|
||||||
@@ -79,7 +78,6 @@ class Game_Temp
|
|||||||
@transition_name = ""
|
@transition_name = ""
|
||||||
@fadestate = 0
|
@fadestate = 0
|
||||||
# Other
|
# Other
|
||||||
@begun_new_game = false
|
|
||||||
@menu_beep = false
|
@menu_beep = false
|
||||||
@memorized_bgm = nil
|
@memorized_bgm = nil
|
||||||
@memorized_bgm_position = 0
|
@memorized_bgm_position = 0
|
||||||
|
|||||||
@@ -22,21 +22,27 @@ class Game_System
|
|||||||
attr_accessor :bgm_position
|
attr_accessor :bgm_position
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@map_interpreter = Interpreter.new(0, true)
|
@map_interpreter = Interpreter.new(0, true)
|
||||||
@battle_interpreter = Interpreter.new(0, false)
|
@battle_interpreter = Interpreter.new(0, false)
|
||||||
@timer_start = nil
|
@timer_start = nil
|
||||||
@timer_duration = 0
|
@timer_duration = 0
|
||||||
@save_disabled = false
|
@save_disabled = false
|
||||||
@menu_disabled = false
|
@menu_disabled = false
|
||||||
@encounter_disabled = false
|
@encounter_disabled = false
|
||||||
@message_position = 2
|
@message_position = 2
|
||||||
@message_frame = 0
|
@message_frame = 0
|
||||||
@save_count = 0
|
@save_count = 0
|
||||||
@magic_number = 0
|
@magic_number = 0
|
||||||
@autoscroll_x_speed = 0
|
@adventure_magic_number = rand(2**32)
|
||||||
@autoscroll_y_speed = 0
|
@autoscroll_x_speed = 0
|
||||||
@bgm_position = 0
|
@autoscroll_y_speed = 0
|
||||||
@bgs_position = 0
|
@bgm_position = 0
|
||||||
|
@bgs_position = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def adventure_magic_number
|
||||||
|
@adventure_magic_number ||= rand(2**32)
|
||||||
|
return @adventure_magic_number
|
||||||
end
|
end
|
||||||
|
|
||||||
def battle_bgm
|
def battle_bgm
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ class GameStats
|
|||||||
attr_accessor :play_sessions
|
attr_accessor :play_sessions
|
||||||
attr_accessor :time_last_saved # In seconds
|
attr_accessor :time_last_saved # In seconds
|
||||||
attr_reader :real_time_saved
|
attr_reader :real_time_saved
|
||||||
|
attr_accessor :save_filename_number # -1 if haven't saved yet
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
# Travel
|
# Travel
|
||||||
@@ -151,6 +152,7 @@ class GameStats
|
|||||||
@play_sessions = 0
|
@play_sessions = 0
|
||||||
@time_last_saved = 0
|
@time_last_saved = 0
|
||||||
@real_time_saved = 0
|
@real_time_saved = 0
|
||||||
|
@save_filename_number = -1
|
||||||
end
|
end
|
||||||
|
|
||||||
def distance_moved
|
def distance_moved
|
||||||
@@ -185,6 +187,11 @@ class GameStats
|
|||||||
return @play_time
|
return @play_time
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# For looking at a save file's play time.
|
||||||
|
def real_play_time
|
||||||
|
return @play_time
|
||||||
|
end
|
||||||
|
|
||||||
def play_time_per_session
|
def play_time_per_session
|
||||||
return play_time / @play_sessions
|
return play_time / @play_sessions
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -286,16 +286,17 @@ MenuHandlers.add(:pause_menu, :save, {
|
|||||||
next $game_system && !$game_system.save_disabled && !pbInSafari? && !pbInBugContest?
|
next $game_system && !$game_system.save_disabled && !pbInSafari? && !pbInBugContest?
|
||||||
},
|
},
|
||||||
"effect" => proc { |menu|
|
"effect" => proc { |menu|
|
||||||
menu.hide_menu
|
pbPlayDecisionSE
|
||||||
scene = PokemonSave_Scene.new
|
ret = false
|
||||||
screen = PokemonSaveScreen.new(scene)
|
pbFadeOutIn do
|
||||||
if screen.pbSaveScreen
|
ret = UI::Save.new.main
|
||||||
menu.silent_end_screen
|
if ret
|
||||||
next true
|
menu.silent_end_screen
|
||||||
|
else
|
||||||
|
menu.refresh
|
||||||
|
end
|
||||||
end
|
end
|
||||||
menu.refresh
|
next ret
|
||||||
menu.show_menu
|
|
||||||
next false
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -335,10 +336,6 @@ MenuHandlers.add(:pause_menu, :quit_game, {
|
|||||||
"effect" => proc { |menu|
|
"effect" => proc { |menu|
|
||||||
menu.hide_menu
|
menu.hide_menu
|
||||||
if pbConfirmMessage(_INTL("Are you sure you want to quit the game?"))
|
if pbConfirmMessage(_INTL("Are you sure you want to quit the game?"))
|
||||||
scene = PokemonSave_Scene.new
|
|
||||||
screen = PokemonSaveScreen.new(scene)
|
|
||||||
screen.pbSaveScreen
|
|
||||||
menu.silent_end_screen
|
|
||||||
$scene = nil
|
$scene = nil
|
||||||
next true
|
next true
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
#
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
class UI::LoadPanel < UI::SpriteContainer
|
class UI::LoadPanel < UI::SpriteContainer
|
||||||
|
attr_writer :label
|
||||||
|
|
||||||
GRAPHICS_FOLDER = "Load/"
|
GRAPHICS_FOLDER = "Load/"
|
||||||
TEXT_COLOR_THEMES = { # These color themes are added to @sprites[:overlay]
|
TEXT_COLOR_THEMES = { # These color themes are added to @sprites[:overlay]
|
||||||
:default => [Color.new(88, 88, 80), Color.new(168, 184, 184)] # Base and shadow colour
|
:default => [Color.new(88, 88, 80), Color.new(168, 184, 184)] # Base and shadow colour
|
||||||
@@ -258,13 +260,16 @@ end
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
class UI::LoadVisuals < UI::BaseVisuals
|
class UI::LoadVisuals < UI::BaseVisuals
|
||||||
attr_reader :slot_index
|
attr_reader :slot_index
|
||||||
|
attr_reader :save_data
|
||||||
|
|
||||||
GRAPHICS_FOLDER = "Load/" # Subfolder in Graphics/UI
|
GRAPHICS_FOLDER = "Load/" # Subfolder in Graphics/UI
|
||||||
PANEL_SPACING_EDGE = 4
|
PANEL_SPACING_EDGE = 4
|
||||||
PANEL_SPACING = PANEL_SPACING_EDGE * 2
|
PANEL_SPACING = PANEL_SPACING_EDGE * 2
|
||||||
|
|
||||||
# save_data here is an array of all save files' data. It has been compacted.
|
# save_data here is an array of [save filename, save data hash]. It has been
|
||||||
# commands is {:continue => _INTL("Continue"), :new_game => _INTL("New Game")}, etc.
|
# compacted.
|
||||||
|
# commands is {:continue => _INTL("Continue"), :new_game => _INTL("New Game")},
|
||||||
|
# etc.
|
||||||
def initialize(commands, save_data, default_slot_index = 0)
|
def initialize(commands, save_data, default_slot_index = 0)
|
||||||
@save_data = save_data
|
@save_data = save_data
|
||||||
@commands = commands
|
@commands = commands
|
||||||
@@ -372,7 +377,13 @@ class UI::LoadVisuals < UI::BaseVisuals
|
|||||||
# Determine whether the Mystery Gift option is visible
|
# Determine whether the Mystery Gift option is visible
|
||||||
@sprites[:mystery_gift].visible = @save_data[@slot_index][1][:player].mystery_gift_unlocked
|
@sprites[:mystery_gift].visible = @save_data[@slot_index][1][:player].mystery_gift_unlocked
|
||||||
refresh_panel_positions
|
refresh_panel_positions
|
||||||
|
# Set the options, and change the language if relevant
|
||||||
|
old_language = $PokemonSystem.language
|
||||||
SaveData.load_bootup_values(@save_data[@slot_index][1], true)
|
SaveData.load_bootup_values(@save_data[@slot_index][1], true)
|
||||||
|
if $PokemonSystem.language != old_language
|
||||||
|
MessageTypes.load_message_files(Settings::LANGUAGES[$PokemonSystem.language][1])
|
||||||
|
full_refresh
|
||||||
|
end
|
||||||
pbPlayCursorSE if !forced
|
pbPlayCursorSE if !forced
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -395,6 +406,7 @@ class UI::LoadVisuals < UI::BaseVisuals
|
|||||||
|
|
||||||
def full_refresh
|
def full_refresh
|
||||||
refresh
|
refresh
|
||||||
|
refresh_labels
|
||||||
@sprites.each_pair { |key, sprite| sprite.refresh if sprite.respond_to?(:refresh) }
|
@sprites.each_pair { |key, sprite| sprite.refresh if sprite.respond_to?(:refresh) }
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -431,6 +443,16 @@ class UI::LoadVisuals < UI::BaseVisuals
|
|||||||
@sprites[:continue_next]&.selected = false
|
@sprites[:continue_next]&.selected = false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def refresh_labels
|
||||||
|
MenuHandlers.each_available(:load_screen, self) do |option, _hash, name|
|
||||||
|
@sprites[option].label = name
|
||||||
|
if option == :continue
|
||||||
|
@sprites[:continue_previous].label = name
|
||||||
|
@sprites[:continue_next].label = name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def refresh_on_index_changed(old_index)
|
def refresh_on_index_changed(old_index)
|
||||||
refresh_selected_panel
|
refresh_selected_panel
|
||||||
refresh_panel_positions
|
refresh_panel_positions
|
||||||
@@ -503,7 +525,7 @@ class UI::Load < UI::BaseScreen
|
|||||||
SCREEN_ID = :load_screen
|
SCREEN_ID = :load_screen
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
load_save_data
|
load_all_save_data
|
||||||
if $DEBUG && !FileTest.exist?("Game.rgssad") && Settings::SKIP_CONTINUE_SCREEN
|
if $DEBUG && !FileTest.exist?("Game.rgssad") && Settings::SKIP_CONTINUE_SCREEN
|
||||||
@disposed = true
|
@disposed = true
|
||||||
perform_action((@save_data.empty?) ? :new_game : :continue)
|
perform_action((@save_data.empty?) ? :new_game : :continue)
|
||||||
@@ -532,22 +554,15 @@ class UI::Load < UI::BaseScreen
|
|||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
def load_save_data
|
# TODO: Move this kind of code into module SaveData.
|
||||||
|
def load_all_save_data
|
||||||
@save_data = []
|
@save_data = []
|
||||||
@default_slot_index = 0
|
@default_slot_index = 0
|
||||||
last_edited_time = nil
|
last_edited_time = nil
|
||||||
files = SaveData.all_save_files
|
files = SaveData.all_save_files
|
||||||
files.each do |file|
|
files.each do |file|
|
||||||
# Load the save file
|
# Load the save file
|
||||||
this_save_data = SaveData.read_from_file(SaveData::DIRECTORY + file)
|
this_save_data = load_save_file(SaveData::DIRECTORY, file)
|
||||||
if !SaveData.valid?(this_save_data)
|
|
||||||
if File.file?(SaveData::DIRECTORY + file + ".bak")
|
|
||||||
show_message(_INTL("The save file is corrupt. A backup will be loaded."))
|
|
||||||
this_save_data = load_save_file(SaveData::FILE_PATH + ".bak")
|
|
||||||
else
|
|
||||||
prompt_corrupted_save_deletion(file)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@save_data.push([file, this_save_data])
|
@save_data.push([file, this_save_data])
|
||||||
# Find the most recently edited save file; default to selecting that one
|
# Find the most recently edited save file; default to selecting that one
|
||||||
save_time = this_save_data[:stats].real_time_saved || 0
|
save_time = this_save_data[:stats].real_time_saved || 0
|
||||||
@@ -557,14 +572,31 @@ class UI::Load < UI::BaseScreen
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
SaveData.load_bootup_values(@save_data[@default_slot_index][1], true) if !@save_data.empty?
|
SaveData.load_bootup_values(@save_data[@default_slot_index][1], true) if !@save_data.empty?
|
||||||
|
MessageTypes.load_message_files(Settings::LANGUAGES[$PokemonSystem.language][1])
|
||||||
|
end
|
||||||
|
|
||||||
|
# TODO: Move this kind of code into module SaveData.
|
||||||
|
def load_save_file(directory, filename)
|
||||||
|
ret = SaveData.read_from_file(directory + filename)
|
||||||
|
if !SaveData.valid?(ret)
|
||||||
|
if File.file?(directory + filename + ".bak")
|
||||||
|
show_message(_INTL("The save file is corrupt. A backup will be loaded."))
|
||||||
|
ret = load_save_file(directory, filename + ".bak")
|
||||||
|
end
|
||||||
|
if prompt_corrupted_save_deletion(filename)
|
||||||
|
delete_save_data(filename)
|
||||||
|
$PokemonSystem = PokemonSystem.new
|
||||||
|
else
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
def prompt_corrupted_save_deletion(filename)
|
def prompt_corrupted_save_deletion(filename)
|
||||||
show_message(_INTL("The save file is corrupt, or is incompatible with this game.") + "\1")
|
show_message(_INTL("The save file is corrupt, or is incompatible with this game.") + "\1")
|
||||||
pbPlayDecisionSE
|
pbPlayDecisionSE
|
||||||
exit if !show_confirm_serious_message(_INTL("Do you want to delete the save file and start anew?"))
|
return show_confirm_serious_message(_INTL("Do you want to delete the save file and start anew?"))
|
||||||
delete_save_data(filename)
|
|
||||||
$PokemonSystem = PokemonSystem.new
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def prompt_save_deletion(filename)
|
def prompt_save_deletion(filename)
|
||||||
@@ -672,6 +704,10 @@ UIActionHandlers.add(UI::Load::SCREEN_ID, :delete_save, {
|
|||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# Menu options that exist in the load screen.
|
# Menu options that exist in the load screen.
|
||||||
|
# NOTE: This can also be called when screen is UI::LoadVisuals (for
|
||||||
|
# retranslating the names upon selecting a save file with a different
|
||||||
|
# language). Try not to have a condition that references things only in
|
||||||
|
# UI::Load.
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
MenuHandlers.add(:load_screen, :continue, {
|
MenuHandlers.add(:load_screen, :continue, {
|
||||||
"name" => _INTL("Continue"),
|
"name" => _INTL("Continue"),
|
||||||
|
|||||||
641
Data/Scripts/016b_UI redesign/014_UI_Save.rb
Normal file
641
Data/Scripts/016b_UI redesign/014_UI_Save.rb
Normal file
@@ -0,0 +1,641 @@
|
|||||||
|
#===============================================================================
|
||||||
|
#
|
||||||
|
#===============================================================================
|
||||||
|
class UI::SavePanel < UI::SpriteContainer
|
||||||
|
attr_reader :sprites
|
||||||
|
|
||||||
|
GRAPHICS_FOLDER = "Save/"
|
||||||
|
TEXT_COLOR_THEMES = { # These color themes are added to @sprites[:overlay]
|
||||||
|
:default => [Color.new(88, 88, 80), Color.new(168, 184, 184)], # Base and shadow colour
|
||||||
|
:white => [Color.new(248, 248, 248), Color.new(172, 188, 188)],
|
||||||
|
:male => [Color.new(0, 112, 248), Color.new(120, 184, 232)],
|
||||||
|
:female => [Color.new(232, 32, 16), Color.new(248, 168, 184)]
|
||||||
|
}
|
||||||
|
PANEL_WIDTH = 384
|
||||||
|
PANEL_HEIGHT = 204
|
||||||
|
|
||||||
|
def initialize(save_data, viewport)
|
||||||
|
@save_data = save_data
|
||||||
|
@show_arrows = false
|
||||||
|
super(viewport)
|
||||||
|
refresh
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize_sprites
|
||||||
|
initialize_panel_background
|
||||||
|
initialize_overlay
|
||||||
|
initialize_player_sprite
|
||||||
|
initialize_pokemon_icons
|
||||||
|
initialize_arrow_sprites
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize_panel_background
|
||||||
|
@sprites[:background] = ChangelingSprite.new(0, 0, @viewport)
|
||||||
|
panel_srcs.each_pair do |key, values|
|
||||||
|
@sprites[:background].add_bitmap(key, values)
|
||||||
|
end
|
||||||
|
@sprites[:background].change_bitmap(:default)
|
||||||
|
record_values(:background)
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize_overlay
|
||||||
|
add_overlay(:overlay, @sprites[:background].width, @sprites[:background].height)
|
||||||
|
@sprites[:overlay].z = 10
|
||||||
|
record_values(:overlay)
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize_player_sprite
|
||||||
|
meta = GameData::PlayerMetadata.get(@save_data[:player].character_ID)
|
||||||
|
filename = pbGetPlayerCharset(meta.walk_charset, @save_data[:player], true)
|
||||||
|
@sprites[:player] = TrainerWalkingCharSprite.new(filename, @viewport)
|
||||||
|
if !@sprites[:player].bitmap
|
||||||
|
raise _INTL("Player character {1}'s walking charset was not found (filename: \"{2}\").",
|
||||||
|
@save_data[:player].character_ID, filename)
|
||||||
|
end
|
||||||
|
@sprites[:player].x = 44 - (@sprites[:player].bitmap.width / 8)
|
||||||
|
@sprites[:player].y = 36 - (@sprites[:player].bitmap.height / 8)
|
||||||
|
@sprites[:player].z = 1
|
||||||
|
record_values(:player)
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize_pokemon_icons
|
||||||
|
Settings::MAX_PARTY_SIZE.times do |i|
|
||||||
|
@sprites["pokemon_#{i}"] = PokemonIconSprite.new(@save_data[:player].party[i], @viewport)
|
||||||
|
@sprites["pokemon_#{i}"].x, @sprites["pokemon_#{i}"].y = pokemon_coords(i)
|
||||||
|
@sprites["pokemon_#{i}"].z = 1
|
||||||
|
@sprites["pokemon_#{i}"].setOffset
|
||||||
|
record_values("pokemon_#{i}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize_arrow_sprites
|
||||||
|
@sprites[:left_arrow] = AnimatedSprite.new(UI_FOLDER + "left_arrow", 8, 40, 28, 2, @viewport)
|
||||||
|
@sprites[:left_arrow].x = -16
|
||||||
|
@sprites[:left_arrow].y = (height / 2) - 14
|
||||||
|
@sprites[:left_arrow].z = 20
|
||||||
|
@sprites[:left_arrow].visible = false
|
||||||
|
@sprites[:left_arrow].play
|
||||||
|
record_values(:left_arrow)
|
||||||
|
@sprites[:right_arrow] = AnimatedSprite.new(UI_FOLDER + "right_arrow", 8, 40, 28, 2, @viewport)
|
||||||
|
@sprites[:right_arrow].x = width - 24
|
||||||
|
@sprites[:right_arrow].y = (height / 2) - 14
|
||||||
|
@sprites[:right_arrow].z = 20
|
||||||
|
@sprites[:right_arrow].visible = false
|
||||||
|
@sprites[:right_arrow].play
|
||||||
|
record_values(:right_arrow)
|
||||||
|
end
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def width
|
||||||
|
return PANEL_WIDTH
|
||||||
|
end
|
||||||
|
|
||||||
|
def height
|
||||||
|
return PANEL_HEIGHT
|
||||||
|
end
|
||||||
|
|
||||||
|
def panel_srcs
|
||||||
|
return {
|
||||||
|
:default => [graphics_folder + "panels", 0, 0, PANEL_WIDTH, PANEL_HEIGHT],
|
||||||
|
:new_slot => [graphics_folder + "panels", 0, PANEL_HEIGHT, PANEL_WIDTH, PANEL_HEIGHT]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def pokemon_coords(index)
|
||||||
|
return 272 + (66 * (index % 2)),
|
||||||
|
36 + (50 * (index / 2))
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_arrows=(value)
|
||||||
|
return if @show_arrows == value
|
||||||
|
@show_arrows = value
|
||||||
|
@sprites[:left_arrow].visible = value
|
||||||
|
@sprites[:right_arrow].visible = value
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_data(save_data)
|
||||||
|
@save_data = save_data
|
||||||
|
@sprites[:background].change_bitmap((@save_data) ? :default : :new_slot)
|
||||||
|
set_player_sprite
|
||||||
|
refresh
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_player_sprite
|
||||||
|
if !@save_data
|
||||||
|
@sprites[:player].visible = false
|
||||||
|
return
|
||||||
|
end
|
||||||
|
@sprites[:player].visible = true
|
||||||
|
meta = GameData::PlayerMetadata.get(@save_data[:player].character_ID)
|
||||||
|
filename = pbGetPlayerCharset(meta.walk_charset, @save_data[:player], true)
|
||||||
|
@sprites[:player].charset = filename
|
||||||
|
if !@sprites[:player].bitmap
|
||||||
|
raise _INTL("Player character {1}'s walking charset was not found (filename: \"{2}\").",
|
||||||
|
@save_data[:player].character_ID, filename)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def refresh
|
||||||
|
super
|
||||||
|
refresh_pokemon
|
||||||
|
draw_save_file_text
|
||||||
|
end
|
||||||
|
|
||||||
|
def refresh_pokemon
|
||||||
|
Settings::MAX_PARTY_SIZE.times do |i|
|
||||||
|
if @save_data
|
||||||
|
@sprites["pokemon_#{i}"].pokemon = @save_data[:player].party[i]
|
||||||
|
@sprites["pokemon_#{i}"].visible = true
|
||||||
|
else
|
||||||
|
@sprites["pokemon_#{i}"].visible = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def draw_save_file_text
|
||||||
|
if !@save_data
|
||||||
|
draw_text(_INTL("Create a new save file"), width / 2, (height / 2) - 10, align: :center)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
gender_theme = :default
|
||||||
|
if @save_data[:player].male?
|
||||||
|
gender_theme = :male
|
||||||
|
elsif @save_data[:player].female?
|
||||||
|
gender_theme = :female
|
||||||
|
end
|
||||||
|
# Player's name
|
||||||
|
draw_text(@save_data[:player].name, 78, 30, theme: gender_theme)
|
||||||
|
# Location
|
||||||
|
map_id = @save_data[:map_factory].map.map_id
|
||||||
|
map_name = pbGetMapNameFromId(map_id)
|
||||||
|
map_name = map_name.gsub(/\\PN/, @save_data[:player].name)
|
||||||
|
map_name = map_name.gsub(/\\v\[(\d+)\]/) { |num| @save_data[:variables][$~[1].to_i].to_s }
|
||||||
|
draw_text(map_name, 14, 78)
|
||||||
|
# Gym Badges
|
||||||
|
draw_text(_INTL("Badges:"), 14, 110, theme: :white)
|
||||||
|
draw_text(@save_data[:player].badge_count.to_s, 222, 110, align: :right)
|
||||||
|
# Pokédex owned count
|
||||||
|
draw_text(_INTL("Pokédex:"), 14, 142, theme: :white)
|
||||||
|
draw_text(@save_data[:player].pokedex.seen_count.to_s, 222, 142, align: :right)
|
||||||
|
# Time played
|
||||||
|
draw_text(_INTL("Play time:"), 14, 174, theme: :white)
|
||||||
|
play_time = @save_data[:stats]&.real_play_time.to_i || 0
|
||||||
|
hour = (play_time / 60) / 60
|
||||||
|
min = (play_time / 60) % 60
|
||||||
|
play_time_text = (hour > 0) ? _INTL("{1}h {2}m", hour, min) : _INTL("{1}m", min)
|
||||||
|
draw_text(play_time_text, 222, 174, align: :right)
|
||||||
|
save_time = @save_data[:stats]&.real_time_saved
|
||||||
|
if save_time
|
||||||
|
save_time = Time.at(save_time)
|
||||||
|
if System.user_language[3..4] == "US" # If the user is in the United States
|
||||||
|
save_text = save_time.strftime("%-m/&-d/%Y")
|
||||||
|
else
|
||||||
|
save_text = save_time.strftime("%-d/%-m/%Y")
|
||||||
|
end
|
||||||
|
draw_text(save_text, PANEL_WIDTH - 14, 174, align: :right)
|
||||||
|
else
|
||||||
|
draw_text("???", PANEL_WIDTH - 14, 174, align: :right)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def refresh_existing_pokemon
|
||||||
|
Settings::MAX_PARTY_SIZE.times do |i|
|
||||||
|
@sprites["pokemon_#{i}"].pokemon = @save_data[:player].party[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
#===============================================================================
|
||||||
|
#
|
||||||
|
#===============================================================================
|
||||||
|
class UI::SaveVisuals < UI::BaseVisuals
|
||||||
|
attr_reader :index
|
||||||
|
|
||||||
|
GRAPHICS_FOLDER = "Save/" # Subfolder in Graphics/UI
|
||||||
|
TEXT_COLOR_THEMES = { # These color themes are added to @sprites[:overlay]
|
||||||
|
:default => [Color.new(80, 80, 88), Color.new(176, 192, 192)] # Base and shadow colour
|
||||||
|
}
|
||||||
|
PANEL_SPACING = 8
|
||||||
|
|
||||||
|
# save_data here is an array of [save filename, save data hash]. It has been
|
||||||
|
# compacted.
|
||||||
|
def initialize(save_data, current_save_data, default_index = 0)
|
||||||
|
@save_data = save_data
|
||||||
|
@current_save_data = current_save_data
|
||||||
|
@index = default_index # Which save slot is selected
|
||||||
|
@choosing_save_file = false
|
||||||
|
super()
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize_sprites
|
||||||
|
initialize_continue_panels
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize_continue_panels
|
||||||
|
# Continue panel in middle
|
||||||
|
this_index = @index
|
||||||
|
@sprites[:continue] = create_slot_panel(this_index)
|
||||||
|
# Continue panel to left
|
||||||
|
if !@save_data.empty?
|
||||||
|
previous_index = this_index - 1
|
||||||
|
@sprites[:continue_previous] = create_slot_panel(this_index - 1)
|
||||||
|
@sprites[:continue_previous].x = @sprites[:continue].x - @sprites[:continue].width - PANEL_SPACING
|
||||||
|
@sprites[:continue_previous].visible = false
|
||||||
|
# Continue panel to right
|
||||||
|
next_index = this_index + 1
|
||||||
|
@sprites[:continue_next] = create_slot_panel(this_index + 1)
|
||||||
|
@sprites[:continue_next].x = @sprites[:continue].x + @sprites[:continue].width + PANEL_SPACING
|
||||||
|
@sprites[:continue_next].visible = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def create_slot_panel(slot_index, initializing = true)
|
||||||
|
slot_index += @save_data.length + 1 if slot_index < 0
|
||||||
|
slot_index -= @save_data.length + 1 if slot_index >= @save_data.length + 1
|
||||||
|
if initializing
|
||||||
|
this_save_data = @current_save_data[1]
|
||||||
|
else
|
||||||
|
this_save_data = (@save_data[slot_index]) ? @save_data[slot_index][1] : nil
|
||||||
|
end
|
||||||
|
ret = UI::SavePanel.new(this_save_data, @viewport)
|
||||||
|
ret.x = (Graphics.width - ret.width) / 2
|
||||||
|
ret.y = 40
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def set_index(new_index, forced = false)
|
||||||
|
while new_index < 0
|
||||||
|
new_index += @save_data.length + 1
|
||||||
|
end
|
||||||
|
while new_index >= @save_data.length + 1
|
||||||
|
new_index -= @save_data.length + 1
|
||||||
|
end
|
||||||
|
return if !forced && @index == new_index
|
||||||
|
# Set the new index
|
||||||
|
@index = new_index
|
||||||
|
# Show the newly selected slot's information in the Continue panel
|
||||||
|
this_save_data = (@save_data[@index]) ? @save_data[@index][1] : nil
|
||||||
|
@sprites[:continue].set_data(this_save_data)
|
||||||
|
# Show the newly adjacent slots' information in the adjacent Continue panels
|
||||||
|
prev_index = @index - 1
|
||||||
|
prev_index += @save_data.length + 1 if prev_index < 0
|
||||||
|
this_save_data = (@save_data[prev_index]) ? @save_data[prev_index][1] : nil
|
||||||
|
@sprites[:continue_previous]&.set_data(this_save_data)
|
||||||
|
next_index = (@index + 1) % (@save_data.length + 1)
|
||||||
|
this_save_data = (@save_data[next_index]) ? @save_data[next_index][1] : nil
|
||||||
|
@sprites[:continue_next]&.set_data(this_save_data)
|
||||||
|
refresh
|
||||||
|
pbPlayCursorSE if !forced
|
||||||
|
end
|
||||||
|
|
||||||
|
def go_to_next_save_slot
|
||||||
|
set_index(@index + 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
def go_to_previous_save_slot
|
||||||
|
set_index(@index - 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def start_choose_save_file
|
||||||
|
@choosing_save_file = true
|
||||||
|
@sprites[:continue_previous].visible = true
|
||||||
|
@sprites[:continue_next].visible = true
|
||||||
|
@sprites[:continue].show_arrows = true
|
||||||
|
set_index(@index, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def refresh_overlay
|
||||||
|
super
|
||||||
|
if @choosing_save_file
|
||||||
|
if @save_data[index] &&
|
||||||
|
@save_data[index][1][:game_system].adventure_magic_number
|
||||||
|
if @save_data[index][1][:game_system].adventure_magic_number == $game_system.adventure_magic_number
|
||||||
|
save_time = @save_data[index][1][:stats].real_play_time
|
||||||
|
delta_time = ($stats.play_time - save_time).to_i
|
||||||
|
hour = (delta_time / 60) / 60
|
||||||
|
min = (delta_time / 60) % 60
|
||||||
|
if hour > 0
|
||||||
|
draw_text(_INTL("Play time since save: {1}h {2}m", hour, min), 8, 4)
|
||||||
|
else
|
||||||
|
draw_text(_INTL("Play time since save: {1}m", min), 8, 4)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
draw_text(_INTL("Different adventure!"), 8, 4)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if @save_data[@index]
|
||||||
|
draw_text(sprintf("%d/%d", @index + 1, @save_data.length), Graphics.width - 8, 4, align: :right)
|
||||||
|
end
|
||||||
|
elsif $stats.save_count > 0 && $stats.real_time_saved
|
||||||
|
save_time = Time.at($stats.real_time_saved)
|
||||||
|
if System.user_language[3..4] == "US" # If the user is in the United States
|
||||||
|
date_text = save_time.strftime("%-m/&-d/%Y")
|
||||||
|
else
|
||||||
|
date_text = save_time.strftime("%-d/%-m/%Y")
|
||||||
|
end
|
||||||
|
time_text = save_time.strftime("%H:%M")
|
||||||
|
draw_text(_INTL("Last saved on {1} at {2}", date_text, time_text), 8, 4)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def full_refresh
|
||||||
|
refresh
|
||||||
|
@sprites.each_pair { |key, sprite| sprite.refresh if sprite.respond_to?(:refresh) }
|
||||||
|
end
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def update_input
|
||||||
|
# Check for movement to a different save slot
|
||||||
|
if Input.repeat?(Input::LEFT)
|
||||||
|
go_to_previous_save_slot
|
||||||
|
elsif Input.repeat?(Input::RIGHT)
|
||||||
|
go_to_next_save_slot
|
||||||
|
end
|
||||||
|
# Check for interaction
|
||||||
|
if Input.trigger?(Input::USE)
|
||||||
|
return update_interaction(Input::USE)
|
||||||
|
elsif Input.trigger?(Input::BACK)
|
||||||
|
return update_interaction(Input::BACK)
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_interaction(input)
|
||||||
|
case input
|
||||||
|
when Input::USE
|
||||||
|
pbPlayDecisionSE
|
||||||
|
return :choose_slot
|
||||||
|
when Input::BACK
|
||||||
|
pbPlayCancelSE
|
||||||
|
return :quit
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def navigate
|
||||||
|
help_text = _INTL("Choose a file to save in.")
|
||||||
|
help_window = Window_AdvancedTextPokemon.newWithSize(
|
||||||
|
help_text, 0, 0, Graphics.width, 96, @viewport
|
||||||
|
)
|
||||||
|
help_window.z = 2000
|
||||||
|
help_window.setSkin(MessageConfig.pbGetSpeechFrame)
|
||||||
|
help_window.letterbyletter = false
|
||||||
|
pbBottomRight(help_window)
|
||||||
|
# Navigate loop
|
||||||
|
ret = super
|
||||||
|
# Clean up
|
||||||
|
help_window.dispose
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
#===============================================================================
|
||||||
|
#
|
||||||
|
#===============================================================================
|
||||||
|
class UI::Save < UI::BaseScreen
|
||||||
|
attr_reader :save_data
|
||||||
|
|
||||||
|
SCREEN_ID = :save_screen
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
create_current_save_data
|
||||||
|
load_all_save_data
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize_visuals
|
||||||
|
@visuals = UI::SaveVisuals.new(@save_data, @current_save_data, @default_index)
|
||||||
|
end
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def index
|
||||||
|
return @visuals&.index || @default_index
|
||||||
|
end
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# This is pseudo-save data containing the current state of the game.
|
||||||
|
def create_current_save_data
|
||||||
|
@current_save_data = [0, {
|
||||||
|
:player => $player,
|
||||||
|
:map_factory => $map_factory,
|
||||||
|
:variables => $game_variables,
|
||||||
|
:stats => $stats
|
||||||
|
}]
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_all_save_data
|
||||||
|
# Load the save file
|
||||||
|
@save_data = []
|
||||||
|
files = SaveData.all_save_files
|
||||||
|
files.each do |file|
|
||||||
|
this_save_data = load_save_file(SaveData::DIRECTORY, file)
|
||||||
|
@save_data.push([file, this_save_data])
|
||||||
|
end
|
||||||
|
# Find the save file index matching the current game's filename number
|
||||||
|
if $stats.save_filename_number && $stats.save_filename_number >= 0
|
||||||
|
expected_filename = SaveData.filename_from_index($stats.save_filename_number)
|
||||||
|
@default_index = @save_data.index { |sav| sav[0] == expected_filename }
|
||||||
|
@default_index ||= @save_data.length # Just in case
|
||||||
|
else
|
||||||
|
@default_index = @save_data.length # New save slot
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def load_save_file(directory, filename)
|
||||||
|
ret = SaveData.read_from_file(directory + filename)
|
||||||
|
if !SaveData.valid?(ret)
|
||||||
|
if File.file?(directory + filename + ".bak")
|
||||||
|
show_message(_INTL("The save file is corrupt. A backup will be loaded."))
|
||||||
|
ret = load_save_file(directory, filename + ".bak")
|
||||||
|
end
|
||||||
|
if prompt_corrupted_save_deletion(filename)
|
||||||
|
delete_save_data(filename)
|
||||||
|
else
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
def prompt_corrupted_save_deletion(filename)
|
||||||
|
show_message(_INTL("The save file is corrupt, or is incompatible with this game.") + "\1")
|
||||||
|
pbPlayDecisionSE
|
||||||
|
return show_confirm_serious_message(_INTL("Do you want to delete the save file and start anew?"))
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete_save_data(filename)
|
||||||
|
begin
|
||||||
|
SaveData.delete_file(filename)
|
||||||
|
yield if block_given?
|
||||||
|
show_message(_INTL("The save file was deleted."))
|
||||||
|
rescue SystemCallError
|
||||||
|
show_message(_INTL("The save file could not be deleted."))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def different_adventure?(slot_index)
|
||||||
|
return false if !@save_data[slot_index]
|
||||||
|
return false if !@save_data[slot_index][1][:game_system].adventure_magic_number
|
||||||
|
return @save_data[slot_index][1][:game_system].adventure_magic_number != $game_system.adventure_magic_number
|
||||||
|
end
|
||||||
|
|
||||||
|
def prompt_overwrite_save_file(slot_index)
|
||||||
|
if different_adventure?(slot_index)
|
||||||
|
show_message(_INTL("WARNING!") + "\1")
|
||||||
|
show_message(_INTL("There is a different game file that is already saved.") + "\1")
|
||||||
|
show_message(_INTL("If you save now, the other file's adventure, including items and Pokémon, will be entirely lost.") + "\1")
|
||||||
|
if !show_confirm_serious_message(_INTL("Are you sure you want to save now and overwrite the other save file?"))
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
# NOTE: Save filenames are "Game#.rxdata" where "#" is slot_index, except for
|
||||||
|
# 0 which just produces "Game.rzdata". This is to support old save
|
||||||
|
# files which are that name.
|
||||||
|
def save_game(file_number)
|
||||||
|
# TODO: I don't know about this "GUI save choice" being here.
|
||||||
|
# pbSEPlay("GUI save choice")
|
||||||
|
if Game.save(file_number)
|
||||||
|
# Refresh the panels to show the new save's data
|
||||||
|
file = SaveData.filename_from_index(file_number)
|
||||||
|
slot_index = @save_data.index { |sav| sav[0] == file }
|
||||||
|
slot_index ||= @save_data.length # New save file
|
||||||
|
this_save_data = load_save_file(SaveData::DIRECTORY, file)
|
||||||
|
@save_data[slot_index] = [file, this_save_data]
|
||||||
|
@visuals.set_index(slot_index, true)
|
||||||
|
# Announce the save success
|
||||||
|
show_message(_INTL("{1} saved the game.", $player.name)) {
|
||||||
|
# TODO: Stop SE.
|
||||||
|
pbMEPlay("GUI save game")
|
||||||
|
# TODO: Wait for ME to finish playing, then auto-close the message.
|
||||||
|
}
|
||||||
|
@result = true
|
||||||
|
else
|
||||||
|
show_message(_INTL("Save failed."))
|
||||||
|
# TODO: Auto-close this message.
|
||||||
|
@result = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_save_file_number(slot_index = -1)
|
||||||
|
filename = (slot_index >= 0 && @save_data[slot_index]) ? @save_data[slot_index][0] : @save_data.last[0]
|
||||||
|
filename[SaveData::FILENAME_REGEX] # Just to get the number in the filename
|
||||||
|
ret = $~[1].to_i
|
||||||
|
ret += 1 if slot_index < 0 || !@save_data[slot_index]
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def full_refresh
|
||||||
|
@visuals.full_refresh
|
||||||
|
end
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def main
|
||||||
|
start_screen
|
||||||
|
# If the player doesn't want to save, just exit the screen
|
||||||
|
if !show_confirm_message(_INTL("Would you like to save the game?"))
|
||||||
|
end_screen
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
# If there are no existing save files, just save in the first slot
|
||||||
|
if @save_data.empty?
|
||||||
|
save_game(0)
|
||||||
|
end_screen
|
||||||
|
return @result
|
||||||
|
end
|
||||||
|
# If there are existing save files, do something depending on which save
|
||||||
|
# files are allowed to be made
|
||||||
|
case Settings::SAVE_SLOTS
|
||||||
|
when :multiple
|
||||||
|
# Choose a save slot to replace
|
||||||
|
@visuals.start_choose_save_file
|
||||||
|
loop do
|
||||||
|
command = @visuals.navigate
|
||||||
|
break if command == :quit
|
||||||
|
if !@save_data[index] ||
|
||||||
|
show_confirm_message(_INTL("Do you want to overwrite this save file?"))
|
||||||
|
if different_adventure?(index)
|
||||||
|
show_message(_INTL("WARNING!") + "\1")
|
||||||
|
pbPlayDecisionSE
|
||||||
|
show_message(_INTL("This save file is a different adventure.") + "\1")
|
||||||
|
pbPlayDecisionSE
|
||||||
|
show_message(_INTL("If you save now, that adventure, including items and Pokémon, will be entirely lost.") + "\1")
|
||||||
|
pbPlayDecisionSE
|
||||||
|
next if !show_confirm_serious_message(_INTL("Are you sure you want to overwrite it?"))
|
||||||
|
end
|
||||||
|
file_number = get_save_file_number(index)
|
||||||
|
save_game(file_number)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
when :adventure
|
||||||
|
if $stats.save_filename_number && $stats.save_filename_number >= 0 # Was saved previously
|
||||||
|
save_game($stats.save_filename_number)
|
||||||
|
else
|
||||||
|
file_number = get_save_file_number(-1) # New save slot
|
||||||
|
save_game(file_number)
|
||||||
|
end
|
||||||
|
when :one
|
||||||
|
save_game(0) if prompt_overwrite_save_file(0)
|
||||||
|
end
|
||||||
|
end_screen
|
||||||
|
return @result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
#===============================================================================
|
||||||
|
#
|
||||||
|
#===============================================================================
|
||||||
|
def pbSaveScreen
|
||||||
|
ret = false
|
||||||
|
pbFadeOutIn { ret = UI::Save.new.main }
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
def pbEmergencySave
|
||||||
|
oldscene = $scene
|
||||||
|
$scene = nil
|
||||||
|
pbMessage(_INTL("The script is taking too long. The game will restart."))
|
||||||
|
return if !$player
|
||||||
|
filename_number = $stats.save_filename_number || -1
|
||||||
|
filename = SaveData.filename_from_index(filename_number)
|
||||||
|
if SaveData.exists?
|
||||||
|
File.open(SaveData::DIRECTORY + filename, "rb") do |r|
|
||||||
|
File.open(SaveData::DIRECTORY + filename + ".bak", "wb") do |w|
|
||||||
|
loop do
|
||||||
|
s = r.read(4096)
|
||||||
|
break if !s
|
||||||
|
w.write(s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if Game.save(filename_number)
|
||||||
|
pbMessage("\\se[]" + _INTL("The game was saved.") + "\\me[GUI save game]\\wtnp[20]")
|
||||||
|
pbMessage("\\se[]" + _INTL("The previous save file has been backed up.") + "\\wtnp[20]")
|
||||||
|
else
|
||||||
|
pbMessage("\\se[]" + _INTL("Save failed.") + "\\wtnp[30]")
|
||||||
|
end
|
||||||
|
$scene = oldscene
|
||||||
|
end
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
=begin
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
#
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
@@ -107,9 +108,8 @@ end
|
|||||||
#
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
def pbSaveScreen
|
def pbSaveScreen
|
||||||
scene = PokemonSave_Scene.new
|
ret = false
|
||||||
screen = PokemonSaveScreen.new(scene)
|
pbFadeOutIn { ret = UI::Save.new.main }
|
||||||
ret = screen.pbSaveScreen
|
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -137,3 +137,4 @@ def pbEmergencySave
|
|||||||
end
|
end
|
||||||
$scene = oldscene
|
$scene = oldscene
|
||||||
end
|
end
|
||||||
|
=end
|
||||||
Reference in New Issue
Block a user