#============================================================================== # ■ save & load screen customization # Ver 0.02 2012/01/21 Fixed scene for event command “Save screen” # Fixed a bug that was not compatible with "Open" # Ver 0.01 2011/12/25 # http://fweb.midi.co.jp/~mikagami/atelier/ #------------------------------------------------------------------------------ # # Change the appearance of the save screen and load screen with thumbnail. # Save location (map display name) in the save file and the game screen. # # ※Note! # ・Save files that are used before installing this script can no longer be used. # ・Because the thumbnail of the game screen is converted and saved, # Save file size is relatively large. Also, the preview display speed is slow. # ・Although we have confirmed functionality, we do not guarantee zero defects. # ・The author holds the copyrights to this script. 水鏡幻姿 (Mikagami Atelier) #  However, you do not need the author's permission to use, revise, or redistribute this script. #  The author does not have an obligation to fulfill requests to revise the script or complete its unfinished parts. #  Instead of asking another person to revise the script, everybody will be happy if you revise it yourself. # #============================================================================== module DataManager #-------------------------------------------------------------------------- # ◎ Maximum number of save files (overwrite definition) #-------------------------------------------------------------------------- def self.savefile_max return 20 # Set a reasonable amount end #-------------------------------------------------------------------------- # ● Get save folder name #-------------------------------------------------------------------------- def self.save_folder_name return "Save" end #-------------------------------------------------------------------------- # ◎ Save file existence judgment (overwrite definition) #-------------------------------------------------------------------------- def self.save_file_exists? if save_folder_name == "" path = 'Save*.rvdata2' else path = save_folder_name + '/Save*.rvdata2' end !Dir.glob(path).empty? end #-------------------------------------------------------------------------- # ◎ Create file name (overwrite definition) # index : File index #-------------------------------------------------------------------------- def self.make_filename(index) file_name = sprintf("Save%03d.rvdata2", index + 1) if save_folder_name == "" return file_name else return save_folder_name + '/' + file_name end end #-------------------------------------------------------------------------- # ● Execution of save / preview #-------------------------------------------------------------------------- def self.save_game_with_preview(index) begin save_game_without_rescue2(index) rescue delete_save_file(index) false end end #-------------------------------------------------------------------------- # ● Load execution and preview available #-------------------------------------------------------------------------- def self.load_game2(index) load_game_without_rescue2(index) rescue false end #-------------------------------------------------------------------------- # ● Load preview #-------------------------------------------------------------------------- def self.load_preview(index) load_preview_without_rescue(index) rescue nil end #-------------------------------------------------------------------------- # ● Execution of save and preview (no exception handling) #-------------------------------------------------------------------------- def self.save_game_without_rescue2(index) unless FileTest.directory?(save_folder_name) if FileTest.exist?(save_folder_name) msgbox "An error occurred during the save process. Please restart." return false end Dir::mkdir(save_folder_name) unless FileTest.directory?(save_folder_name) msgbox "Save failed. Check your HDD/SSD free space, etc." return false end end File.open(make_filename(index), "wb") do |file| $game_system.on_before_save Marshal.dump(make_save_header2, file) Marshal.dump(make_save_preview, file) Marshal.dump(make_save_contents, file) @last_savefile_index = index end return true end #-------------------------------------------------------------------------- # ● Load execution with preview (no exception handling) #-------------------------------------------------------------------------- def self.load_game_without_rescue2(index) File.open(make_filename(index), "rb") do |file| Marshal.load(file) Marshal.load(file) extract_save_contents(Marshal.load(file)) reload_map_if_updated @last_savefile_index = index end return true end #-------------------------------------------------------------------------- # ● Create / extend save header #-------------------------------------------------------------------------- def self.make_save_header2 header = {} header[:characters] = $game_party.characters_for_savefile header[:playtime_s] = $game_system.playtime_s header[:savetitle] = $game_map.display_name header end #-------------------------------------------------------------------------- # ● Load preview (no exception handling) #-------------------------------------------------------------------------- def self.load_preview_without_rescue(index) File.open(make_filename(index), "rb") do |file| Marshal.load(file) return array_to_bitmap(Marshal.load(file)) end return nil end #-------------------------------------------------------------------------- # ● Create preview #-------------------------------------------------------------------------- def self.make_save_preview preview = bitmap_to_array($game_temp.save_preview_bmp) preview end #-------------------------------------------------------------------------- # ● Convert preview bitmap to saveable array format # bitmap #-------------------------------------------------------------------------- def self.bitmap_to_array(bitmap) return unless bitmap data = [] for i in 0...bitmap.width data[i] = [] for j in 0...bitmap.height color = bitmap.get_pixel(i, j) value = (color.red.floor << 16) + (color.green.floor << 8) + color.blue.floor data[i][j] = value end end return data end #-------------------------------------------------------------------------- # ● Restore preview bitmap from array format to bitmap #-------------------------------------------------------------------------- def self.array_to_bitmap(data) return unless data bitmap = Bitmap.new(data.size, data[0].size) for i in 0...data.size for j in 0...data[0].size red = (data[i][j] >> 16) & 0xff green = (data[i][j] >> 8) & 0xff blue = data[i][j] & 0xff color = Color.new(red, green, blue) bitmap.set_pixel(i, j, color) end end return bitmap end end class Game_Temp #-------------------------------------------------------------------------- # ● Public instance variables #-------------------------------------------------------------------------- attr_accessor :save_preview_bmp # BMP for save preview #-------------------------------------------------------------------------- # ● Object initialization #-------------------------------------------------------------------------- alias _old001_initialize initialize def initialize _old001_initialize @save_preview_bmp = Bitmap.new(1, 1) end #-------------------------------------------------------------------------- # ● BMP for save preview #-------------------------------------------------------------------------- def create_save_preview @save_preview_bmp.dispose if @save_preview_bmp @save_preview_bmp = Bitmap.new(224, 160) rect = Rect.new(0, 0, 224, 160) rect.x = $game_player.screen_x - 112 rect.y = $game_player.screen_y - 80 - 16 bitmap = Graphics.snap_to_bitmap @save_preview_bmp.blt(0, 0, bitmap, rect) bitmap.dispose end end class Game_Party < Game_Unit #-------------------------------------------------------------------------- # ◎ Character image information for save file display (overwrite definition) #-------------------------------------------------------------------------- def characters_for_savefile battle_members.collect do |actor| [actor.character_name, actor.character_index, actor.level, actor.name] end end end #============================================================================== # ■ Window_SaveFileList #------------------------------------------------------------------------------ #  Save file list window displayed on the save & load screen. #============================================================================== class Window_SaveFileList < Window_Selectable #-------------------------------------------------------------------------- # ● Object initialization #-------------------------------------------------------------------------- def initialize(x, y) super(x, y, (Graphics.width - x) / 2, Graphics.height - y) load_savefileheader refresh activate end #-------------------------------------------------------------------------- # ● Get number of items #-------------------------------------------------------------------------- def item_max DataManager.savefile_max end #-------------------------------------------------------------------------- # ● Get item height #-------------------------------------------------------------------------- def item_height (height - standard_padding * 2) / 5 end #-------------------------------------------------------------------------- # ● Drawing items #-------------------------------------------------------------------------- def draw_item(index) rect = item_rect_for_text(index) text_h = rect.y + (rect.height - line_height * 2) / 2 name = Vocab::File + " #{index + 1}" change_color(system_color) draw_text(rect.x, text_h, rect.width, line_height, name) return unless @data[index] change_color(normal_color) draw_playtime(rect.x, text_h, rect.width, line_height, index) draw_savetitle(rect.x, text_h + line_height, rect.width, line_height, index) end #-------------------------------------------------------------------------- # ● Processing when the enter button is pressed #-------------------------------------------------------------------------- def process_ok call_ok_handler # Process with scene class end #-------------------------------------------------------------------------- # ● Read all save file headers #-------------------------------------------------------------------------- def load_savefileheader @data = [] for i in 0...item_max do @data[i] = DataManager.load_header(i) end end #-------------------------------------------------------------------------- # ● Drawing play time #-------------------------------------------------------------------------- def draw_playtime(x, y, width, height, i) draw_text(x, y, width, height, @data[i][:playtime_s], 2) end #-------------------------------------------------------------------------- # ● Drawing save titles #-------------------------------------------------------------------------- def draw_savetitle(x, y, width, height, i) title = @data[i][:savetitle] title = "<NO TITLE>" if title == "" draw_text(x, y, width, height, title) end end #============================================================================== # ■ Window_SaveFilePreview #------------------------------------------------------------------------------ #  This is the save file window displayed during save & load screen. #============================================================================== class Window_SaveFilePreview < Window_Base #-------------------------------------------------------------------------- # ● Object initialization #-------------------------------------------------------------------------- def initialize(x, y) super(x, y, Graphics.width - x, Graphics.height - y) @file_no = -1 @bmps = [] @data = [] end #-------------------------------------------------------------------------- # ● Dispose #-------------------------------------------------------------------------- def dispose for bmp in @bmps next if bmp == nil or bmp.disposed? bmp.dispose end super end #-------------------------------------------------------------------------- # ● Load save file and display preview # file_no : Save file number #-------------------------------------------------------------------------- def set_preview(file_no) return if @file_no == file_no @file_no = file_no refresh end #-------------------------------------------------------------------------- # ● Refresh #-------------------------------------------------------------------------- def refresh self.contents.clear load_preview(@file_no) return unless @data[@file_no] bitmap = @bmps[@file_no] start_x = (contents.width - bitmap.width) / 2 contents.fill_rect(start_x - 1, 7, bitmap.width + 2, bitmap.height + 2, Color.new(0, 0, 0)) contents.blt(start_x, 8, bitmap, bitmap.rect) header = @data[@file_no] header[:characters].each_with_index do |data, i| break if i >= 4 character_y = bitmap.height + 22 + i * 40 draw_character(data[0], data[1], start_x + 16, character_y + 28) draw_level_for_preview(data[2], start_x + 40, character_y) draw_name_for_preview(data[3], start_x + 100, character_y, bitmap.width - start_x - 100) end end #-------------------------------------------------------------------------- # ● Load preview data #-------------------------------------------------------------------------- def load_preview(file_no) return if @data[file_no] @bmps[file_no] = DataManager.load_preview(file_no) return unless @bmps[file_no] @data[file_no] = DataManager.load_header(file_no) end #-------------------------------------------------------------------------- # ● Level drawing #-------------------------------------------------------------------------- def draw_level_for_preview(level, x, y) change_color(system_color) draw_text(x, y, 24, line_height, Vocab::level_a) change_color(normal_color) draw_text(x + 24, y, 24, line_height, level, 2) end #-------------------------------------------------------------------------- # ● Actor name drawing #-------------------------------------------------------------------------- def draw_name_for_preview(name, x, y, width) change_color(normal_color) draw_text(x, y, width, line_height, name) end end class Scene_File < Scene_MenuBase #-------------------------------------------------------------------------- # ◎ Start processing (overwrite definition) #-------------------------------------------------------------------------- def start super create_help_window @filelist_window = Window_SaveFileList.new(0, @help_window.height) @filelist_window.set_handler(:ok, method(:on_savefile_ok)) @filelist_window.set_handler(:cancel, method(:on_savefile_cancel)) @preview_window = Window_SaveFilePreview.new(@filelist_window.width, @help_window.height) init_selection end #-------------------------------------------------------------------------- # ◎ End processing (overwrite definition) #-------------------------------------------------------------------------- def terminate super end #-------------------------------------------------------------------------- # ◎ Initialize selected state (overwrite definition) #-------------------------------------------------------------------------- def init_selection index = first_savefile_index @filelist_window.select(index) @preview_window.set_preview(index) end #-------------------------------------------------------------------------- # ◎ Frame update (overwrite definition) #-------------------------------------------------------------------------- def update super @preview_window.set_preview(@filelist_window.index) end end class Scene_Save < Scene_File #-------------------------------------------------------------------------- # ◎ Save file (overwrite definition) #-------------------------------------------------------------------------- def on_savefile_ok super if DataManager.save_game_with_preview(@filelist_window.index) on_save_success else Sound.play_buzzer end end end class Scene_Load < Scene_File #-------------------------------------------------------------------------- # ◎ Save file (overwrite definition) #-------------------------------------------------------------------------- def on_savefile_ok super if DataManager.load_game2(@filelist_window.index) on_load_success else Sound.play_buzzer end end end class Scene_Map < Scene_Base #-------------------------------------------------------------------------- # ◎ End processing #-------------------------------------------------------------------------- alias _old001_terminate terminate def terminate $game_temp.create_save_preview _old001_terminate end end