RPG Maker Forums

I have a problem that I don't know how to solve.

The idea:
- After the XY event ends in RPG Maker, call Save Scene and overwrite a save file but only update $game_switches in that file. Other things inside the file leave as it is. After that is done, go to the title screen of the game.

The purpose of this is to allow the player to replay endings after he's seen them. Since all the ending events end with the player going to the title screen of the game, I need to save somewhere information that the player has seen that event before that happens. For that purpose, I made it so XY switch is flipped before the player is transferred to the title screen, and Save Scene is called so that the switch I flipped is saved inside the latest save file.

Ideally, I would've liked it somehow all existing save files would be automatically edited and the switch change saved inside them, but I don't even know where to begin.

Anyhow, I ended up messing around and came up with a way to do it on just one file. But, it's not working as I planned... The solution is probably something stupid but I can't figure it out.

--------------------------
MY THOUGHT PROCESS
--------------------------

There are two functions that I need to adjust to being able to pull this off.

1ST FUNCTION
Code:
def on_decision(filename)
    $game_system.se_play($data_system.save_se)
    file = File.open(filename, "wb")
    write_save_data(file)
    file.close
    if $game_temp.save_calling
       $game_temp.save_calling = false
       $scene = Scene_Map.new
       return
    end
      $scene = Scene_Menu.new(4)
end
2ND FUNCTION
Code:
def write_save_data(file)
      characters = []
      for i in 0...$game_party.actors.size
        actor = $game_party.actors[i]
        characters.push([actor.character_name, actor.character_hue])
      end
      Marshal.dump(characters, file)
      Marshal.dump(Graphics.frame_count, file)
      $game_system.save_count += 1
      $game_system.magic_number = $data_system.magic_number
      Marshal.dump($game_system, file)
      Marshal.dump($game_switches, file)
      Marshal.dump($game_variables, file)
      Marshal.dump($game_self_switches, file)
      Marshal.dump($game_screen, file)
      Marshal.dump($game_actors, file)
      Marshal.dump($game_party, file)
      Marshal.dump($game_troop, file)
      Marshal.dump($game_map, file)
      Marshal.dump($game_player, file)
end
So, the first thing I did was to replace the 3rd line inside the first function with all this:

Code:
if $game_switches[1100] == true
  file = File.open(filename, "rb+")
else
  file = File.open(filename, "wb")
end
Before the Save Screen is called inside the ending event, I flipped a switch 1100 to ON so the script knows it only needs to update $game_switches inside an existing save file. To that end, I made inside the first function an if-else loop. According to the wiki or ruby, "rb+" is for when I only want to update something inside the existing file so I opened the file with "rb+" instead of "wb" that deletes everything inside the file first.

After that I edited the 2nd function to this:
Code:
def write_save_data(file)
  if $game_switches[1100] == false
      characters = []
      for i in 0...$game_party.actors.size
        actor = $game_party.actors[i]
        characters.push([actor.character_name, actor.character_hue])
      end
      Marshal.dump(characters, file)
      Marshal.dump(Graphics.frame_count, file)
      $game_system.save_count += 1
      $game_system.magic_number = $data_system.magic_number
      Marshal.dump($game_system, file)
      Marshal.dump($game_variables, file)
      Marshal.dump($game_self_switches, file)
      Marshal.dump($game_screen, file)
      Marshal.dump($game_actors, file)
      Marshal.dump($game_party, file)
      Marshal.dump($game_troop, file)
      Marshal.dump($game_map, file)
      Marshal.dump($game_player, file)
  end
      Marshal.dump($game_switches, file)
end
I moved the "Marshal.dump($game_switches, file)" outside the IF loop so only that part gets updated in case switch 1100 is FALSE. If 1100 is TRUE(which in my case it is), everything inside the if loop will be skipped.

Everything works exactly as I thought it would expect for this error when I try to open a save file I saved after I did these changes.



This is the script it's referring to inside the error that I didn't change at all...
Code:
=begin
セーブ数増量(当社比)XP用
Ver 0.0.2
by 半生
http://www.tktkgame.com


 セーブ可能ファイル数を増加(当社比)させます

 ver 0.0.3
  ・セーブ1~4がないとコンテニュー出来なかった不具合修正
 ver 0.0.2
  ・画面切り替え時にviewportを開放するように修正
=end


#==============================================================================
# ■ Scene_File
#------------------------------------------------------------------------------
# セーブ画面およびロード画面のスーパークラスです。
# MAX_FILE : セーブファイルの上限
#==============================================================================
class Scene_File
  MAX_ITEM = 40 # セーブファイルの上限
  #--------------------------------------------------------------------------
  # ● オブジェクト初期化
  #     help_text : ヘルプウィンドウに表示する文字列
  #--------------------------------------------------------------------------
  alias :_hn__initialize :initialize unless method_defined?(:_hn__initialize)
  def initialize(help_text)
    @viewport = Viewport.new(0, 64, 640, 416)
    @top_row = 0
    _hn__initialize(help_text)
  end

  #--------------------------------------------------------------------------
  # ● メイン処理
  #--------------------------------------------------------------------------
  # 再定義
  def main
    # ヘルプウィンドウを作成
    @help_window = Window_Help.new
    @help_window.set_text(@help_text, 1)
    # セーブファイルウィンドウを作成
    @savefile_windows = []
    for i in 0...MAX_ITEM
      @savefile_windows.push(Window_SaveFile.new(i, make_filename(i), @viewport))
    end
    # 最後に操作したファイルを選択
    self.index = $game_temp.last_file_index
    @savefile_windows[@file_index].selected = true
    # トランジション実行
    Graphics.transition
    # メインループ
    loop do
      # ゲーム画面を更新
      Graphics.update
      # 入力情報を更新
      Input.update
      # フレーム更新
      update
      # 画面が切り替わったらループを中断
      if $scene != self
        break
      end
    end
    # トランジション準備
    Graphics.freeze
    # ウィンドウを解放
    @help_window.dispose
    for i in @savefile_windows
      i.dispose
    end
    # Viewportを開放
    @viewport.dispose
  end

  def index=(index)
    @file_index = index % MAX_ITEM
    if @file_index < @top_row
      @top_row = @file_index
    elsif @file_index > @top_row + 3
      @top_row = [@file_index - 3, 0].max
    end
    @viewport.oy = @top_row * 104
  end

  #--------------------------------------------------------------------------
  # ● フレーム更新
  #--------------------------------------------------------------------------
  # 再定義
  def update
    # ウィンドウを更新
    @help_window.update
    for i in @savefile_windows
      i.update
    end
    # C ボタンが押された場合
    if Input.trigger?(Input::C)
      # メソッド on_decision (継承先で定義) を呼ぶ
      on_decision(make_filename(@file_index))
      $game_temp.last_file_index = @file_index
      return
    end
    # B ボタンが押された場合
    if Input.trigger?(Input::B)
      # メソッド on_cancel (継承先で定義) を呼ぶ
      on_cancel
      return
    end
    # 方向ボタンの下が押された場合
    if Input.repeat?(Input::DOWN)
      # 方向ボタンの下の押下状態がリピートでない場合か、
      # またはカーソル位置が 3 より前の場合
      if Input.trigger?(Input::DOWN) or @file_index < MAX_ITEM
        # カーソル SE を演奏
        $game_system.se_play($data_system.cursor_se)
        # カーソルを下に移動
        @savefile_windows[@file_index].selected = false
        self.index = (@file_index + 1) % MAX_ITEM
        @savefile_windows[@file_index].selected = true
        return
      end
    end
    # 方向ボタンの上が押された場合
    if Input.repeat?(Input::UP)
      # 方向ボタンの上の押下状態がリピートでない場合か、
      # またはカーソル位置が 0 より後ろの場合
      if Input.trigger?(Input::UP) or @file_index > 0
        # カーソル SE を演奏
        $game_system.se_play($data_system.cursor_se)
        # カーソルを上に移動
        @savefile_windows[@file_index].selected = false
        self.index = (@file_index - 1) % MAX_ITEM
        @savefile_windows[@file_index].selected = true
        return
      end
    end
  end
end

#==============================================================================
# ■ Scene_Load
#------------------------------------------------------------------------------
# ロード画面の処理を行うクラスです。
#==============================================================================

class Scene_Load
  # 再定義
  def initialize
    # テンポラリオブジェクトを再作成
    $game_temp = Game_Temp.new
    # タイムスタンプが最新のファイルを選択
    $game_temp.last_file_index = 0
    latest_time = Time.at(0)
    for i in 0...Scene_File::MAX_ITEM
      filename = make_filename(i)
      if FileTest.exist?(filename)
        file = File.open(filename, "r")
        if file.mtime > latest_time
          latest_time = file.mtime
          $game_temp.last_file_index = i
        end
        file.close
      end
    end
    super("Which file do you want to load?")
  end
end

#==============================================================================
# ■ Window_Base
#------------------------------------------------------------------------------
# Viewportを指定できるように拡張
#==============================================================================
class Window_Base
  # 再定義
  def initialize(x, y, width, height, viewport = nil)
    if viewport.is_a?(Viewport)
      super(viewport)
    else
      super()
    end
    @windowskin_name = $game_system.windowskin_name
    self.windowskin = RPG::Cache.windowskin(@windowskin_name)
    self.x = x
    self.y = y
    self.width = width
    self.height = height
    self.z = 100
  end
end

#==============================================================================
# ■ Window_SaveFile
#------------------------------------------------------------------------------
# セーブ画面およびロード画面で表示する、セーブファイルのウィンドウです。
#==============================================================================
class Window_SaveFile
  # 再定義
  def initialize(file_index, filename, viewport = nil)
    if viewport.is_a?(Viewport)
      super(0, 64 + file_index * 104 - viewport.rect.y, 640, 104, viewport)
    else
      super(0, 64 + file_index * 104, 640, 104)
    end
  
    self.contents = Bitmap.new(width - 32, height - 32)
    @file_index = file_index
    @filename = "Save#{@file_index + 1}.rxdata"
    @time_stamp = Time.at(0)
    @file_exist = FileTest.exist?(@filename)
    if @file_exist
      file = File.open(@filename, "r")
      @time_stamp = file.mtime
      @characters = Marshal.load(file)
      @frame_count = Marshal.load(file)
      @game_system = Marshal.load(file)
      @game_switches = Marshal.load(file)
      @game_variables = Marshal.load(file)
      @total_sec = @frame_count / Graphics.frame_rate
      file.close
    end
    refresh
    @selected = false
  end
end

class Scene_Title
  #--------------------------------------------------------------------------
  # ● メイン処理
  #--------------------------------------------------------------------------
  def main
    # 戦闘テストの場合
    if $BTEST
      battle_test
      return
    end
    # データベースをロード
    $data_actors        = load_data("Data/Actors.rxdata")
    $data_classes       = load_data("Data/Classes.rxdata")
    $data_skills        = load_data("Data/Skills.rxdata")
    $data_items         = load_data("Data/Items.rxdata")
    $data_weapons       = load_data("Data/Weapons.rxdata")
    $data_armors        = load_data("Data/Armors.rxdata")
    $data_enemies       = load_data("Data/Enemies.rxdata")
    $data_troops        = load_data("Data/Troops.rxdata")
    $data_states        = load_data("Data/States.rxdata")
    $data_animations    = load_data("Data/Animations.rxdata")
    $data_tilesets      = load_data("Data/Tilesets.rxdata")
    $data_common_events = load_data("Data/CommonEvents.rxdata")
    $data_system        = load_data("Data/System.rxdata")
    # システムオブジェクトを作成
    $game_system = Game_System.new
    # タイトルグラフィックを作成
    @sprite = Sprite.new
    @sprite.bitmap = RPG::Cache.title($data_system.title_name)
    # コマンドウィンドウを作成
    s1 = "New Game"
    s2 = "Continue"
    s3 = "Game End"
    @command_window = Window_Command.new(192, [s1, s2, s3])
    @command_window.back_opacity = 160
    @command_window.x = 140 - @command_window.width / 2 - 40
    @command_window.y = 308+40
    # コンティニュー有効判定
    # セーブファイルがひとつでも存在するかどうかを調べる
    # 有効なら @continue_enabled を true、無効なら false にする
    @continue_enabled = false
    for i in 0..(Scene_File::MAX_ITEM-1)
      if FileTest.exist?("Save#{i+1}.rxdata")
        @continue_enabled = true
      end
    end
    # コンティニューが有効な場合、カーソルをコンティニューに合わせる
    # 無効な場合、コンティニューの文字をグレー表示にする
    if @continue_enabled
      @command_window.index = 1
    else
      @command_window.disable_item(1)
    end
    # タイトル BGM を演奏
    $game_system.bgm_play($data_system.title_bgm)
    # ME、BGS の演奏を停止
    Audio.me_stop
    Audio.bgs_stop
    # トランジション実行
    Graphics.transition
    # メインループ
    loop do
      # ゲーム画面を更新
      Graphics.update
      # 入力情報を更新
      Input.update
      # フレーム更新
      update
      # 画面が切り替わったらループを中断
      if $scene != self
        break
      end
    end
    # トランジション準備
    Graphics.freeze
    # コマンドウィンドウを解放
    @command_window.dispose
    # タイトルグラフィックを解放
    @sprite.bitmap.dispose
    @sprite.dispose
  end
end

Latest Threads

Latest Profile Posts

Day 9 of giveaways! 8 prizes today :D
He mad, but he cute :kaopride:

Our latest feature is an interview with... me?!

People4_2 (Capelet off and on) added!

Just beat the last of us 2 last night and starting jedi: fallen order right now, both use unreal engine & when I say i knew 80% of jedi's buttons right away because they were the same buttons as TLOU2 its ridiculous, even the same narrow hallway crawl and barely-made-it jump they do. Unreal Engine is just big budget RPG Maker the way they make games nearly identical at its core lol.

Forum statistics

Threads
106,038
Messages
1,018,467
Members
137,821
Latest member
Capterson
Top