Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Quick Save /Load

Basically, I want to be able to "quick-save".
As in, saving even in the middle of battle/etc.
When loading the game, I wanna make it continue exactly from the same spot.

First, does anyone know if there is such a script out there?
If not, I need help to write it.

The base code will be my edit to Zeriab's F12 pause script.
Rather than just pausing the game when you hit F12, you can choose if to save your game or cancel. After you save/cancel, the game goes back to the scene you came from: map, battle, menu, etc.
The process is:
- save the value of $scene
- call scene_save
- return to the game by doing $scene= old_scene.
However, some scenes do restart, since the game's main loop calls $scene.main again.
When saving, I guess I can store all the variables of the scene into the save file, and load them back.
My problem is this- I understand Ruby has no go_to functionality. How can I start from the middle of a method? Maybe by utilizing 'eval' ?
Also, I need to know the number of the line currently being executed, so I'll know where to continue from. Does anyone know how to do that?
 
You really shouldn't try to save in the middle of a method, if possible. Set a variable somewhere that will tell the scene to save, and then at the beginning of the next frame (before main, Graphics.update, etc) have the save actually occur. If there's anything you have to do after the save you should be able to put it off until the next frame, and since the setup should be the same when you load it will execute normally.
 
How do I tell I'm in the middle of a method?
I could change a variable to true at the start of each method, and to false when it ends.. but then my script won't be compatible with any script that doesn't do the same.
 
Make a method under your scene (or Scene_Base with the SDK, etc) that flips a variable true, like @suspending = true. This is what you'll call when you want to quick save; something like $scene.suspend .Then in the main as the very first thing have it check if you're @suspending
[rgss]if @suspending
  scene_suspend
  @suspending = false
end
[/rgss]

and have the method scene_suspend be a copy of Scene_Save#write_save_data (create a file, Marshal.dump things into it, close file)
 
Interesting idea.
The check should be inside the usual loop in main (break if $scene!=self), right?
I'm thinking, instead of editing every scene, why not do it inside Scene_Base update ?
[rgss]class Scene_Base
 alias scene_update update
 def update
   if $game_temp.quick_save
     # save the game, including the value of $scene
     $game_temp.quick_save = false
   end
   if $game_temp.quick_load
     # load the game normally + load all scene variables from the file
     $scene.handle_quick_load  
     $game_temp.quick_load = false
   end
   scene_update
 end
 
end
[/rgss]
handle_quick_load can be the same method for all scenes- it'll just do the main loop without resetting the scene's variables. in other words-
[rgss]class Scene_Base
   # -------------------------------------------------------- #
   # Do the usual loop, without calling scene.main.                  #
   # in battle, for example, calling main will restart everything.   #
   # -------------------------------------------------------- #
 def handle_quick_load
    Graphics.transition
    loop do
      Graphics.update
      Input.update
      update
      if $scene != self
        break
      end
    end
    Graphics.freeze
    dispose_windows
 end
 
 def dispose_windows
   for var in self.instance_variables
     eval ("if #{var}.is_a?(Window_Base) : #{var}.dispose end")
   end
 end
 
end
[/rgss]

Now, if only I could set $game_temp.quick_save to true when not in the middle of a method..
 
ok, I've made some progress on this.
I'm currently trying to deep-copy a scene object using a custom Marshal.dump method.
I have a few questions about this:
- Marshal.dump has 3 parameters by default: Marshal.dump(object,file,depth), the last 2 are optional. However, my custom method _dump does not receive these parameters- only depth is sent! Does this mean Ruby saves the returned string automatically to the file, or do I have to do so myself?
- Why does Marshal.load return a string, shouldn't it return a new object?

For reference, I use this code to auto-saves the game:
[rgss]class Scene_File
 
  # Don't wait for player's input on auto-save.
  alias file_update update
  def update
    auto_save? ? save_and_return : file_update    
  end
 
  def auto_save?
    return ($game_temp.force_save) #and self.is_a?(Scene_Save)
  end
 
  def save_and_return
    # call scene_save:: auto_save
    auto_save
    $game_temp.force_save = false
    # Switch to map screen. will be changed later to auto_load
    $scene = Scene_Map.new
    # Inform the player
    $game_temp.message_text = "Your game has been saved !"
  end
 
end
 
 
class Scene_Save < Scene_File
 
  def initialize
    super("")
  end
 
  def auto_save
    filename = "Save1.rxdata"
    on_decision(filename)
  end
 
end
[/rgss]
[rgss]class Game_Temp
 
  attr_accessor  :load_flag   # was the game quick-loaded
  attr_accessor  :saved_scene
 
  def quick_save
    @force_save = true
    save_scene($scene)
    $scene = Scene_Save.new
  end
 
 # not tested yet
  def quick_load
    return if @saved_scene.nil?
    # deep copy
    $scene = Marshal.load( Marshal.dump(@saved_scene) )
    $scene.load_all
    @load_flag = true
  end
 
 
  def save_scene(scene)
    # deep copy
    @saved_scene = Marshal.load( Marshal.dump(scene) )
  end
 
  # this method is made for testing
  def marshal_test
     # class Super_Simple < Scene_Base
     x = Super_Simple.new
     x2 =  Marshal.load( Marshal.dump(x) )
  end
 
end
 
class << Input
  alias input_update update
  def update            
    Input.input_update
    # auto save: press F5
    $game_temp.quick_save if Input.trigger?(Input::F5)
    # auto load: press F6
    $game_temp.quick_load if Input.trigger?(Input::F6)
  end
 
end
[/rgss]

Here is my Scene_Base, with my _dump method.
It is not finished yet.
(my Scene_Base is not an edit of SDK, but a new one)

[rgss]class Scene_Base
  # -----------------------------------------#
  #  main calls this instead of $scene.main,     #
  #       if $game_temp.load_flag = true          #
  # -----------------------------------------#
  def main_loop
    load_all
    loop do
      Graphics.update
      Input.update
      update
      if $scene != self
        break
      end
    end
    dispose_all  
  end
 
  def dispose_all
    # dispose all windows
    for var in self.instance_variables
      window_var = eval ("#{var}.is_a?(Window_Base)")
      if window_var : var.dispose end
    end
   
  end
 
# not tested yet
  def load_all
    saved_scene = Marshal.load( Marshal.dump($game_temp.saved_scene) )
    for var in self.instance_variables
      old_value = saved_scene.instance_variable_get(var)
      self.instance_variable_set(var,old_value)
    end
   
  end
 
  def _dump(depth)
    file = File.open('filename', File::WRONLY|File::CREAT)
    data = "#<"
    data += self.class.name + ":"
    data += self.object_id.to_s + " "
    for var in self.instance_variables
      cont = self.instance_variable_get(var)
      data += var + "="
      data += to_str(cont)
      data +=", "
    end
    data += ">"
    file.puts data
    file.close
    return data
  end
 
  def to_str(x)
    if x.is_a?(String)
      q = '"'
      return (q + x + q)
    end
    return x.to_s if x.is_a?(Fixnum)
    if x.is_a?(Array)
      str = "["
      n = x.size
      for i in 0...n-1
        str += to_str( x ) + ","
      end
      str += to_str( x[n-1] ) + "]"
      return str
    end
   
  end
 
  def self._load(file)
    aFile = File.open(file, "rb")
    data_table = IO.readlines(file)
    return data_table[0]
  end
 
end
[/rgss]
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top