#============================================================================== # ■ セーブ&ロード画面をカスタマイズするスクリプト # Ver 0.02 2012/01/21 Sceneクラス関連を修正、イベントコマンド「セーブ画面を # 開く」に未対応だった不具合を修正 # Ver 0.01 2011/12/25 # http://fweb.midi.co.jp/~mikagami/atelier/ #------------------------------------------------------------------------------ # # セーブ画面とロード画面の見た目を少し変更します。 # セーブファイルに「セーブした場所(マップの表示名)」とゲーム画面の # スクリーンショットを追加します。 # また、セーブファイルを「Save」フォルダへ保存するようにします。 # # ※注意! # ・スクリプト導入前に使用していたセーブファイルは使用できなくなります。 # ・他にセーブ&ロード画面をカスタマイズするスクリプトを導入している場合、 #  競合が起こる可能性は高いと思います。 # ・ゲーム画面のスクリーンショットを変換して保存している関係上、セーブファイルの #  ファイルサイズが比較的大きくなります。また、プレビューの表示速度が遅いです。 # ・ひととおりの動作確認はしていますが、不具合ゼロを保障するものではありません。 # ・このスクリプトの著作権は著者にあります。 #  ですがスクリプトの利用や改造・再配布に著者の許可は必要ありません。 #  著者には未完成な部分の補完や改造依頼に対する対応義務はありません。 #  他者に改造依頼するより、あなた自身が改造すれば、みんなが幸せになります。 # #============================================================================== module DataManager #-------------------------------------------------------------------------- # ◎ セーブファイルの最大数(上書き定義) #-------------------------------------------------------------------------- def self.savefile_max return 20 # 大きすぎないこと! end #-------------------------------------------------------------------------- # ● セーブフォルダ名の取得 #-------------------------------------------------------------------------- def self.save_folder_name return "Save" end #-------------------------------------------------------------------------- # ◎ セーブファイルの存在判定(上書き定義) #-------------------------------------------------------------------------- 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 #-------------------------------------------------------------------------- # ◎ ファイル名の作成(上書き定義) # 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 #-------------------------------------------------------------------------- # ● セーブの実行・プレビューあり #-------------------------------------------------------------------------- def self.save_game_with_preview(index) begin save_game_without_rescue2(index) rescue delete_save_file(index) false end end #-------------------------------------------------------------------------- # ● ロードの実行・プレビューあり #-------------------------------------------------------------------------- def self.load_game2(index) load_game_without_rescue2(index) rescue false end #-------------------------------------------------------------------------- # ● プレビューのロード #-------------------------------------------------------------------------- def self.load_preview(index) load_preview_without_rescue(index) rescue nil end #-------------------------------------------------------------------------- # ● セーブの実行・プレビューあり(例外処理なし) #-------------------------------------------------------------------------- def self.save_game_without_rescue2(index) unless FileTest.directory?(save_folder_name) if FileTest.exist?(save_folder_name) msgbox "セーブ処理で異常が発生しました。ゲームを再インストールして下さい。" return false end Dir::mkdir(save_folder_name) unless FileTest.directory?(save_folder_name) msgbox "セーブに失敗しました。HDDの空き容量等を確認して下さい。" 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 #-------------------------------------------------------------------------- # ● ロードの実行・プレビューあり(例外処理なし) #-------------------------------------------------------------------------- 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 #-------------------------------------------------------------------------- # ● セーブヘッダの作成・拡張 #-------------------------------------------------------------------------- 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 #-------------------------------------------------------------------------- # ● プレビューのロード(例外処理なし) #-------------------------------------------------------------------------- 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 #-------------------------------------------------------------------------- # ● プレビューの作成 #-------------------------------------------------------------------------- def self.make_save_preview preview = bitmap_to_array($game_temp.save_preview_bmp) preview end #-------------------------------------------------------------------------- # ● プレビュー用ビットマップをセーブ可能な配列形式に変換する # 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 #-------------------------------------------------------------------------- # ● プレビュー用ビットマップを配列形式からビットマップに復元する #-------------------------------------------------------------------------- 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 #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_accessor :save_preview_bmp # セーブプレビュー用BMP #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- alias _old001_initialize initialize def initialize _old001_initialize @save_preview_bmp = Bitmap.new(1, 1) end #-------------------------------------------------------------------------- # ● セーブプレビュー用BMP #-------------------------------------------------------------------------- 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 #-------------------------------------------------------------------------- # ◎ セーブファイル表示用のキャラクター画像情報(上書き定義) #-------------------------------------------------------------------------- def characters_for_savefile battle_members.collect do |actor| [actor.character_name, actor.character_index, actor.level, actor.name] end end end #============================================================================== # ■ Window_SaveFileList #------------------------------------------------------------------------------ #  セーブ&ロード画面で表示する、セーブファイル一覧のウィンドウです。 #============================================================================== class Window_SaveFileList < Window_Selectable #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize(x, y) super(x, y, (Graphics.width - x) / 2, Graphics.height - y) load_savefileheader refresh activate end #-------------------------------------------------------------------------- # ● 項目数の取得 #-------------------------------------------------------------------------- def item_max DataManager.savefile_max end #-------------------------------------------------------------------------- # ● 項目の高さを取得 #-------------------------------------------------------------------------- def item_height (height - standard_padding * 2) / 5 end #-------------------------------------------------------------------------- # ● 項目の描画 #-------------------------------------------------------------------------- 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 #-------------------------------------------------------------------------- # ● 決定ボタンが押されたときの処理 #-------------------------------------------------------------------------- def process_ok call_ok_handler # シーンクラスで処理する end #-------------------------------------------------------------------------- # ● 全セーブファイルのヘッダーを読み込み #-------------------------------------------------------------------------- def load_savefileheader @data = [] for i in 0...item_max do @data[i] = DataManager.load_header(i) end end #-------------------------------------------------------------------------- # ● プレイ時間の描画 #-------------------------------------------------------------------------- def draw_playtime(x, y, width, height, i) draw_text(x, y, width, height, @data[i][:playtime_s], 2) end #-------------------------------------------------------------------------- # ● セーブのタイトルの描画 #-------------------------------------------------------------------------- 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 #------------------------------------------------------------------------------ #  セーブ&ロード画面で表示する、セーブファイルの詳細ウィンドウです。 #============================================================================== class Window_SaveFilePreview < Window_Base #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize(x, y) super(x, y, Graphics.width - x, Graphics.height - y) @file_no = -1 @bmps = [] @data = [] end #-------------------------------------------------------------------------- # ● 解放 #-------------------------------------------------------------------------- def dispose for bmp in @bmps next if bmp == nil or bmp.disposed? bmp.dispose end super end #-------------------------------------------------------------------------- # ● セーブファイルをロードしてプレビューを表示 # file_no : セーブファイル番号 #-------------------------------------------------------------------------- def set_preview(file_no) return if @file_no == file_no @file_no = file_no refresh end #-------------------------------------------------------------------------- # ● リフレッシュ #-------------------------------------------------------------------------- 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 #-------------------------------------------------------------------------- # ● プレビュー用のデータを読み込む #-------------------------------------------------------------------------- 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 #-------------------------------------------------------------------------- # ● レベルの描画 #-------------------------------------------------------------------------- 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 #-------------------------------------------------------------------------- # ● アクター名の描画 #-------------------------------------------------------------------------- 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 #-------------------------------------------------------------------------- # ◎ 開始処理(上書き定義) #-------------------------------------------------------------------------- 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 #-------------------------------------------------------------------------- # ◎ 終了処理(上書き定義) #-------------------------------------------------------------------------- def terminate super end #-------------------------------------------------------------------------- # ◎ 選択状態の初期化(上書き定義) #-------------------------------------------------------------------------- def init_selection index = first_savefile_index @filelist_window.select(index) @preview_window.set_preview(index) end #-------------------------------------------------------------------------- # ◎ フレーム更新(上書き定義) #-------------------------------------------------------------------------- def update super @preview_window.set_preview(@filelist_window.index) end end class Scene_Save < Scene_File #-------------------------------------------------------------------------- # ◎ セーブファイルの決定(上書き定義) #-------------------------------------------------------------------------- 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 #-------------------------------------------------------------------------- # ◎ セーブファイルの決定(上書き定義) #-------------------------------------------------------------------------- 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 #-------------------------------------------------------------------------- # ◎ 終了処理 #-------------------------------------------------------------------------- alias _old001_terminate terminate def terminate $game_temp.create_save_preview _old001_terminate end end