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.

[VX] Advanced Files

Advanced Files
by Dargor
Version 1.3


Introduction

This script let you customize some aspects of save files. You can have as much save files as you want, change the filename, extension and directory of the files and have a confirmation window before loading or overwriting a file. This script also modifies the File scene and adds a detail window that displays party members stats, gold, map name and a preview of the location.

Screenshots


Script

Code:
#==============================================================================

# ** Advanced Files

#------------------------------------------------------------------------------

#  Â© Dargor, 2008-2009

#  25/03/09

#  Version 1.3

#  Part of the credits goes to Yeyinde for the Bitmap dump/load methods

#------------------------------------------------------------------------------

#  VERSION HISTORY:

#   - 1.0 (27/06/08), Initial release

#   - 1.1 (05/07/08), Added support for Location Name Picture instead of text

#   - 1.2 (17/02/09), Fixed a bug with wrong actors stats being displayed 

#   - 1.3 (25/03/09), Fixed a bug with map preview not being loaded correctly 

#------------------------------------------------------------------------------

#  INTRODUCTION:

#     This script let you customize some aspects of save files.

#     You can have as much save files as you want, change the filename,

#     extension and directory of the files and have a confirmation window

#     before loading or overwriting a file.

#------------------------------------------------------------------------------

#  INSTRUCTIONS:

#   - Paste this script above main

#   - Edit the constants in Advanced_Files module

#==============================================================================

 

# Vocabulary

Vocab::SaveMessage = "Save to which file?"

Vocab::LoadMessage = "Load which file?"

Vocab::File = 'File'

Vocab::NoFile = 'Empty'

Vocab::FileConfirm = 'Are you sure you want to %s this file?'

 

#==============================================================================

# ** Advanced Files Configuration Module

#==============================================================================

 

module Advanced_Files

  # Maximum number of files

  Max_Files = 10

  # Filename

  Name = 'Save'

  # File extension

  Extension = 'rvdata'

  # File directory (Automatically creates the directory)

  Directory = 'Save'

  # Use file confirmation

  Confirmation = true

  # Smooth Scroll

  Smooth_Scroll = true

  # Scroll Speed (The higher the faster)

  Scroll_Speed = 30

  # Use a picture for location name instead of text

  Location_Name_Picture = false

end

 

#==============================================================================

# ** Font

#==============================================================================

 

class Font

  def marshal_dump;end

  def marshal_load(obj);end

end

 

#==============================================================================

# ** Bitmap

#==============================================================================

 

class Bitmap

  # Win32API

  RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')

  RtlMoveMemory_ip = Win32API.new('kernel32', 'RtlMoveMemory', 'ipi', 'i')

  #--------------------------------------------------------------------------

  # * Dump

  #--------------------------------------------------------------------------

  def _dump(limit)

    data = "rgba" * width * height

    RtlMoveMemory_pi.call(data, address, data.length)

    [width, height, Zlib::Deflate.deflate(data)].pack("LLa*")

  end

  #--------------------------------------------------------------------------

  # * Load

  #--------------------------------------------------------------------------

  def self._load(str)

    w, h, zdata = str.unpack("LLa*"); b = new(w, h)

    RtlMoveMemory_ip.call(b.address, Zlib::Inflate.inflate(zdata), w * h * 4); b

  end

  #--------------------------------------------------------------------------

  # * Address

  #--------------------------------------------------------------------------

  def address

    buffer, ad = "xxxx", object_id * 2 + 16

    RtlMoveMemory_pi.call(buffer, ad, 4); ad = buffer.unpack("L")[0] + 8

    RtlMoveMemory_pi.call(buffer, ad, 4); ad = buffer.unpack("L")[0] + 16

    RtlMoveMemory_pi.call(buffer, ad, 4); return buffer.unpack("L")[0]

  end

end

 

#==============================================================================

# ** Game_System

#------------------------------------------------------------------------------

#  This class handles system-related data. Also manages vehicles and BGM, etc.

# The instance of this class is referenced by $game_system.

#==============================================================================

 

class Game_System

  #--------------------------------------------------------------------------

  # * Public Instance Variables

  #--------------------------------------------------------------------------

  attr_accessor :background_bitmap

  attr_accessor :map_name

  #--------------------------------------------------------------------------

  # * Alias Listing

  #--------------------------------------------------------------------------

  alias dargor_advanced_files_system_initialize initialize

  #--------------------------------------------------------------------------

  # * Object Initialization

  #--------------------------------------------------------------------------

  def initialize

    dargor_advanced_files_system_initialize

    @background_bitmap = nil

    @map_name = ''

  end

end

 

#==============================================================================

# ** Game_Map

#------------------------------------------------------------------------------

#  This class handles maps. It includes scrolling and passage determination

# functions. The instance of this class is referenced by $game_map.

#==============================================================================

 

class Game_Map

  #--------------------------------------------------------------------------

  # * Get Map ID

  #--------------------------------------------------------------------------

  def name

    map_infos = load_data("Data/MapInfos.rvdata")

    name = map_infos[@map_id].name

    return name

  end

end

 

#==============================================================================

# ** Window_FileBase

#------------------------------------------------------------------------------

#  This is a superclass of all file windows in the game.

#==============================================================================

 

class Window_FileBase < Window_Base

  #--------------------------------------------------------------------------

  # * Load Game Data

  #--------------------------------------------------------------------------

  def load_gamedata(filename)

    @filename = filename

    @time_stamp = Time.at(0)

    @file_exist = FileTest.exist?(@filename)

    if @file_exist

      file = File.open(@filename, "rb")

      @time_stamp = file.mtime

      begin

        @characters     = Marshal.load(file)

        @frame_count    = Marshal.load(file)

        @last_bgm       = Marshal.load(file)

        @last_bgs       = Marshal.load(file)

        @game_system    = Marshal.load(file)

        @game_message   = Marshal.load(file)

        @game_switches  = Marshal.load(file)

        @game_variables = Marshal.load(file)

        @game_self_switches  = Marshal.load(file)

        @game_actors         = Marshal.load(file)

        @game_party          = Marshal.load(file)

        @game_troop          = Marshal.load(file)

        @game_map            = Marshal.load(file)

        @game_player         = Marshal.load(file)

        @actors = Marshal.load(file)

        @total_sec = @frame_count / Graphics.frame_rate

      rescue

        @file_exist = false

      ensure

        file.close

      end

    end

    refresh

  end

end

 

#==============================================================================

# ** Window_MapPreview

#------------------------------------------------------------------------------

#  This window displays a map preview in the File screen.

#==============================================================================

 

class Window_MapPreview < Window_FileBase

  #--------------------------------------------------------------------------

  # * Object Initialization

  #--------------------------------------------------------------------------

  def initialize

    super(272, 212,264,196)

    self.visible = false

  end

  #--------------------------------------------------------------------------

  # * Refresh

  #--------------------------------------------------------------------------

  def refresh

    self.contents.clear

    return unless @file_exist

    name = @game_system.map_name

    if Advanced_Files::Location_Name_Picture

      bitmap = Cache.picture(name)

      self.contents.blt(4,4,bitmap,bitmap.rect)

    else

      self.contents.draw_text(4,4,272,WLH,name)

    end

    bitmap = @game_system.background_bitmap

    bitmap = Bitmap.new(32,32) if bitmap.nil?

    self.contents.blt(4,32,bitmap,Rect.new(160,128,224,128))

  end

end

 

#==============================================================================

# ** Window_FileDetail

#------------------------------------------------------------------------------

#  This window displays file details in the File screen.

#==============================================================================

 

class Window_FileDetail < Window_FileBase

  #--------------------------------------------------------------------------

  # * Object Initialization

  #--------------------------------------------------------------------------

  def initialize

    super(0,202,544,214)

    self.visible = false

  end

  #--------------------------------------------------------------------------

  # * Refresh

  #--------------------------------------------------------------------------

  def refresh

    self.contents.clear

    return unless @file_exist

    if @game_system.instance_variables.include?('@difficulty_id')

      y = 24

      self.contents.font.color = system_color

      self.contents.draw_text(4,0, 240, WLH, 'Difficulty:')

      self.contents.font.color = normal_color

      difficulty = Difficulty::Names[@game_system.difficulty_id]

      self.contents.draw_text(96,0, 240, WLH, difficulty)

    else

      y = 0

    end

    for actor in @actors

      i = @actors.index(actor)

      draw_actor_name(actor,4,y + i * WLH)

      draw_actor_hp(actor,96,y + i * WLH)

    end

  end

end

 

#==============================================================================

# ** Window_FileGold

#------------------------------------------------------------------------------

#  This window displays the amount of gold in the File screen.

#==============================================================================

 

class Window_FileGold < Window_FileBase

  #--------------------------------------------------------------------------

  # * Object Initialization

  #--------------------------------------------------------------------------

  def initialize

    super(108, 352, 160, WLH + 32)

    self.visible = false

  end

  #--------------------------------------------------------------------------

  # * Refresh

  #--------------------------------------------------------------------------

  def refresh

    self.contents.clear

    draw_currency_value(@game_party.gold, 4, 0, 120)

  end

end

 

#==============================================================================

# ** Window_SaveFile

#------------------------------------------------------------------------------

#  This window displays save files on the save and load screens.

#==============================================================================

 

class Window_SaveFile < Window_Base

  MAX_FILES = Advanced_Files::Max_Files

  #--------------------------------------------------------------------------

  # * Public Instance Variables

  #--------------------------------------------------------------------------

  attr_reader :file_index

  #--------------------------------------------------------------------------

  # * Alias Listing

  #--------------------------------------------------------------------------

  alias dargor_vx_advanced_files_window_refresh refresh

  #--------------------------------------------------------------------------

  # * Object Initialization

  #     file_index : save file index (0-3)

  #     filename   : filename

  #--------------------------------------------------------------------------

  def initialize(file_index, filename)

    super(0, file_index % MAX_FILES * 90, 544, 90)

    @file_index = file_index

    @filename = filename

    load_gamedata

    refresh

    @selected = false

  end

  #--------------------------------------------------------------------------

  # * Refresh

  #--------------------------------------------------------------------------

  def refresh

    dargor_vx_advanced_files_window_refresh

    unless @file_exist

      y = (self.height / 2)-(WLH / 2)

      self.contents.draw_text(0,y,508,WLH,Vocab::NoFile,2)

    end

  end

end

 

#==============================================================================

# ** Scene_Title

#------------------------------------------------------------------------------

#  This class performs the title screen processing.

#==============================================================================

 

class Scene_Title < Scene_Base

  #--------------------------------------------------------------------------

  # * Determine if Continue is Enabled

  #--------------------------------------------------------------------------

  def check_continue

    name = Advanced_Files::Name

    extension = Advanced_Files::Extension

    directory = Advanced_Files::Directory

    unless FileTest.directory?(directory)

      Dir.mkdir(directory)

    end

    @continue_enabled = (Dir.glob("#{directory}/#{name}*.#{extension}").size > 0)

  end

end

 

#==============================================================================

# ** Scene_File

#------------------------------------------------------------------------------

#  This class performs the save and load screen processing.

#==============================================================================

 

class Scene_File < Scene_Base

  MAX_FILES = Advanced_Files::Max_Files

  #--------------------------------------------------------------------------

  # * Alias Listing

  #--------------------------------------------------------------------------

  alias dargor_vx_advanced_files_scene_file_start start

  alias dargor_vx_advanced_files_scene_file_terminate terminate

  alias dargor_vx_advanced_files_scene_file_update update

  alias dargor_vx_advanced_files_scene_file_update_savefile_windows update_savefile_windows

  alias dargor_vx_advanced_files_scene_file_write_save_data write_save_data

  alias dargor_vx_advanced_files_scene_file_read_save_data read_save_data

  #--------------------------------------------------------------------------

  # * Create Save File Window

  #--------------------------------------------------------------------------

  def create_savefile_windows

    @savefile_windows = []

    @file_viewport = Viewport.new(0,56,544,416)

    @file_viewport.z = 500

    @old_top_row = 0

    @speed = 0

    for i in 0...MAX_FILES

      @savefile_windows.push(Window_SaveFile.new(i, make_filename(i)))

      @savefile_windows[i].viewport = @file_viewport

    end

    @item_max = MAX_FILES

  end

  #--------------------------------------------------------------------------

  # * Start Processing

  #--------------------------------------------------------------------------

  def start

    dargor_vx_advanced_files_scene_file_start

    create_command_window

    @detail_window = Window_FileDetail.new

    @map_window = Window_MapPreview.new

    @gold_window = Window_FileGold.new

  end

  #--------------------------------------------------------------------------

  # * Terminate Processing

  #--------------------------------------------------------------------------

  def terminate

    dargor_vx_advanced_files_scene_file_terminate

    @command_window.dispose

    @detail_window.dispose

    @map_window.dispose

    @gold_window.dispose

  end

  #--------------------------------------------------------------------------

  # * Create Command Window

  #--------------------------------------------------------------------------

  def create_command_window

    @command_window = Window_Command.new(544,['Yes','No'],2)

    @command_window.active = false

    @command_window.visible = false

    @command_window.y = 56

    @command_window.z = 501

  end

  #--------------------------------------------------------------------------

  # * Frame Update

  #--------------------------------------------------------------------------

  def update 

    @command_window.update

    @detail_window.update

    @map_window.update

    @gold_window.update

    @detail_window.visible = @command_window.visible

    @map_window.visible = @command_window.visible

    @gold_window.visible = @command_window.visible

    if @command_window.active

      update_command_window

      return

    end

    dargor_vx_advanced_files_scene_file_update

  end

  #--------------------------------------------------------------------------

  # * Frame Update (Command Window)

  #--------------------------------------------------------------------------

  def update_command_window

    unless $game_map.nil?

      @spriteset.update unless @spriteset.nil?

    end

    if Input.trigger?(Input::B)

      Sound.play_cancel

      close_confirmation_window

    end

    if Input.trigger?(Input::C)

      case @command_window.index

      when 0

        if @saving

          Sound.play_save

          do_save

        else

          Sound.play_load

          do_load

        end

      when 1

        Sound.play_cancel

        close_confirmation_window

      end

    end

  end

  #--------------------------------------------------------------------------

  # * Open Confirmation Window

  #--------------------------------------------------------------------------

  def open_confirmation_window

    window_to_top

    for window in @savefile_windows

      window.visible = false unless window.file_index == @index

    end

    mode = @saving ? 'overwrite' : 'load'

    text = sprintf(Vocab::FileConfirm, mode)

    @help_window.set_text(text)

    @detail_window.load_gamedata(@savefile_windows[@index].filename)

    @map_window.load_gamedata(@savefile_windows[@index].filename)

    @gold_window.load_gamedata(@savefile_windows[@index].filename)

    @command_window.visible = true

    @command_window.active = true

  end

  #--------------------------------------------------------------------------

  # * Close Confirmation Window

  #--------------------------------------------------------------------------

  def close_confirmation_window

    self.top_row = @old_top_row

    for window in @savefile_windows

      window.visible = true

    end

    if @saving

      text = Vocab::SaveMessage

    else

      text = Vocab::LoadMessage

    end

    @help_window.set_text(text)

    @command_window.visible = false

    @command_window.active = false

  end

  #--------------------------------------------------------------------------

  # * Get Top Row

  #--------------------------------------------------------------------------

  def top_row

    return @file_viewport.oy / 90

  end

  #--------------------------------------------------------------------------

  # * Get Top Row

  #--------------------------------------------------------------------------

  def top_row=(index)

    @file_viewport.oy = index * 90

  end

  #--------------------------------------------------------------------------

  # * Get Bottom Row

  #--------------------------------------------------------------------------

  def bottom_row

    return top_row + 3

  end

  #--------------------------------------------------------------------------

  # * Get Top Row

  #--------------------------------------------------------------------------

  def window_to_top

    @file_viewport.oy = @index * 90

    @file_viewport.oy -= 56

  end

  #--------------------------------------------------------------------------

  # * Confirm Save File

  #--------------------------------------------------------------------------

  def determine_savefile

    if @saving

      if @savefile_windows[@index].file_exist

        if Advanced_Files::Confirmation

          Sound.play_decision

          open_confirmation_window

        else

          Sound.play_save

          do_save

        end

      else

        Sound.play_save

        do_save

      end

    else

      if @savefile_windows[@index].file_exist

        if Advanced_Files::Confirmation

          Sound.play_decision

          open_confirmation_window

        else

          Sound.play_load

          do_load

        end

      else

        Sound.play_buzzer

        return

      end

    end

    $game_temp.last_file_index = @index

  end

  #--------------------------------------------------------------------------

  # * Update Save File Window

  #--------------------------------------------------------------------------

  def update_savefile_windows

    dargor_vx_advanced_files_scene_file_update_savefile_windows

    # Update file viewport

    if @index < top_row

      if Advanced_Files::Smooth_Scroll

        loop do

          Graphics.update

          Input.update

          if Graphics.frame_count % 30 == 0

            @speed = [[@speed + 1, 6].min, 0].max

          end

          dist = 5 * (Advanced_Files::Scroll_Speed + @speed) 

          @file_viewport.oy = [[@file_viewport.oy - dist, MAX_FILES * 90].min, @index * 90].max

          break if @file_viewport.oy == @index * 90

        end

      else

        @file_viewport.oy = @index * 90

      end

    elsif @index > bottom_row

      if Advanced_Files::Smooth_Scroll

        loop do

          Graphics.update

          Input.update

          if Graphics.frame_count % 30 == 0

            @speed = [[@speed + 1, 6].min, 0].max

          end

          dist = 5 * (Advanced_Files::Scroll_Speed + @speed) 

          @file_viewport.oy = [[@file_viewport.oy + dist, 0].max, (@index - 3) * 90].min

          break if @file_viewport.oy  == (@index - 3) * 90

        end

      else

        @file_viewport.oy  = (@index - 3) * 90

      end

    else

      @speed = [[@speed - 1, 0].max, 6].min

    end

  end

  #--------------------------------------------------------------------------

  # * Create Filename

  #     file_index : save file index (0-3)

  #--------------------------------------------------------------------------

  def make_filename(file_index)

    name = Advanced_Files::Name

    extension = Advanced_Files::Extension

    directory = Advanced_Files::Directory

    unless FileTest.directory?(directory)

      Dir.mkdir(directory)

    end

    return "#{directory}/#{name}#{file_index + 1}.#{extension}"

  end

  #--------------------------------------------------------------------------

  # * Write Save Data

  #     file : write file object (opened)

  #--------------------------------------------------------------------------

  def write_save_data(file)

    dargor_vx_advanced_files_scene_file_write_save_data(file)

    actors = []

    for actor in $game_party.members

      actors.push(actor)

    end

    Marshal.dump(actors, file)

  end

  #--------------------------------------------------------------------------

  # * Read Save Data

  #     file : read file object (opened)

  #--------------------------------------------------------------------------

  def read_save_data(file)

    dargor_vx_advanced_files_scene_file_read_save_data(file)

    @actors = Marshal.load(file)

  end

end

 

#==============================================================================

# ** Scene_Map

#------------------------------------------------------------------------------

#  This class performs the map screen processing.

#==============================================================================

 

class Scene_Map

  #--------------------------------------------------------------------------

  # * Alias Listing

  #--------------------------------------------------------------------------

  alias dargor_vx_advanced_files_map_call_menu call_menu

  alias dargor_vx_advanced_files_map_call_save call_save

  #--------------------------------------------------------------------------

  # * Switch to Menu Screen

  #--------------------------------------------------------------------------

  def call_menu

    $game_system.background_bitmap = Graphics.snap_to_bitmap

    $game_system.map_name = $game_map.name

    dargor_vx_advanced_files_map_call_menu

  end

  #--------------------------------------------------------------------------

  # * Switch to Menu Screen

  #--------------------------------------------------------------------------

  def call_save

    $game_system.background_bitmap = Graphics.snap_to_bitmap

    $game_system.map_name = $game_map.name

    dargor_vx_advanced_files_map_call_save

  end

end

 
[/spoiler]

Credits and Thanks

Part of the credits goes to Yeyinde for the Bitmap dump/load methods

Hope you like it!
-Dargor
 
Wow... just wow.
EDIT: I get an error when I scroll past the 4th save file space thingy. (I have a small vocabulary :down: )
 
Hmm, well, if you manage to get it working, this could be really nifty! I especially like how it shows your location. Just a question, though, do you have to add pictures yourself of the location, or does the script do that for you?
 
I'm sorry, but this script doesn't seem to work at all for me. I don't get any errors, but the save load screens are the same as the ones previously before I installed the script.....

EDIT: I just noticed I have 80 save slots now, but the save/load screen like in the screenshot still doesn't show for me.
 
dootthaloop":180222aw said:
I'm sorry, but this script doesn't seem to work at all for me. I don't get any errors, but the save load screens are the same as the ones previously before I installed the script.....
It works fine for me...?
 
King Red Of Pancakes":ipve3emx said:
dootthaloop":ipve3emx said:
I'm sorry, but this script doesn't seem to work at all for me. I don't get any errors, but the save load screens are the same as the ones previously before I installed the script.....
It works fine for me...?

Oh I'm sorry, I see what I did, I turned off the confirmation -__-; I thought it was some minor option I didn't need... when I actually wanted it XD Now I feel stupid....
 
This doesn't seem to work with Anaryu's Anti-Lag script.

What i did: I loaded the game, then I pressed F12 to go back to the title screen again.  I then went to new game again, and it game me an error.
"Script 'AS:Anit-Lag' line 83:System StackError occurred.
stack level too deep"

=P
 
This is a cool alright detailed loading screen, which isn't cluttered. I give you 3.5/5, because the only thing I could see you adding that won't over detail it would be a small loading bar, when it is preparing the information (just in case of slow computers), and for when loading the actually game up, showing the status conditions on the player, showing the SP, and EXP, and above the play time ammount display having the date of the time saved (I would add more space if possible if adding that, just don't overload it like I did in this post I would recommend most of them though). Also cool screenshot feature, could you please convert that part of the code into RGSS for me, I would like to see how you did that? Very nice job making this script Dargor, looks great.
 
@val helblaze
Sure, I can do that.

@diablosbud 
I give you 3.5/5, because the only thing I could see you adding that won't over detail it would be a small loading bar, when it is preparing the information (just in case of slow computers)
A loading bar would be totally useless. There is not enough things to load. Even on a slow computer, the bar would not update while the graphics are showing up simply because during the slowdown, the graphics don't (and can't) update.

and for when loading the actually game up, showing the status conditions on the player, showing the SP, and EXP
I'm not sure what you mean here.

and above the play time amount display having the date of the time saved
Adding the date is a good idea. I'll do that.

Also cool screenshot feature, could you please convert that part of the code into RGSS for me
You mean convert it for XP'S RGSS1? It's not possible. Well, it is, but it requires an external dll. The 'screenshot feature' I'm using is a default feature of the Graphics module in RGSS2, I did nothing new there.
 
I have updated the script and I have added this feature.
You have to set Location_Name_Picture to true; the pictures must be placed in the Pictures directory and must have the same name as the map.
 
Dargor":3ayo7666 said:
I have updated the script and I have added this feature.
You have to set Location_Name_Picture to true; the pictures must be placed in the Pictures directory and must have the same name as the map.

Sweet. Will I have to resize the images myself or will it automatically resize to fit the space?
 

Taylor

Sponsor

A bug! A bug! Squish it!

Even though one hero has 998 (lol testing max) HP and one is knocked out, they all have full health according to the load screen.
The same error is in the save screen but different, HP is based on current file in-game rather than the file being previewed.
 

maia

Member

I get an error... can't find Graphics/Pictures/interiors.

EDIT: I just read the item about how I need to have my own photos in the directory with the map name. Is that correct?
 

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