File Size Based Save System
Version: 1.0
Introduction
This script changes the default save system to one that uses file sizes instead of one that uses an index. Because it uses a file size, I allow the player to name his/her save file to whatever he/she wants (using legal characters, of course).
Features
Screenshots
Please note that these screenshots are from my game, Tropicana. The system here looks similar, but it doesn't have the selection window, batter gauge and connectivity metre.
http://i12.photobucket.com/albums/a229/ ... ystem2.png[/IMG]http://i12.photobucket.com/albums/a229/meismeofcourse/Savesystem3.png[/IMG]
Script
Looks like the families get a lucky break today.
Instructions
FAQ
No questions asked
Compatibility
May be SDK compatible (conformation needed). Should be compatible with scripts that add to the save files.
Author's Notes
This script was originally developed for my game, Tropicana. I just thought I'd share it with you all.
Version: 1.0
Introduction
This script changes the default save system to one that uses file sizes instead of one that uses an index. Because it uses a file size, I allow the player to name his/her save file to whatever he/she wants (using legal characters, of course).
Features
- Easy to use
- Can name your own save file!
- Customizable memory capacity
- Customizable file extension
Screenshots
Please note that these screenshots are from my game, Tropicana. The system here looks similar, but it doesn't have the selection window, batter gauge and connectivity metre.
http://i12.photobucket.com/albums/a229/ ... ystem2.png[/IMG]http://i12.photobucket.com/albums/a229/meismeofcourse/Savesystem3.png[/IMG]
Script
Looks like the families get a lucky break today.
Code:
#==============================================================================
# ** File Size Based Save System (FSBSS)
#------------------------------------------------------------------------------
# © Yeyinde, 2007
#==============================================================================
module FSBSS
# Maximum memory capacity (in Mega Bytes (MB)) - Floating points may be used.
MAXIMUM_MEMORY = 0.5
# Save file extension, leave out the .
# Please don't name it something like ini or exe, this may cause errors.
SAVE_FILE_EXT = 'rxdata'
# Temporary save extension, do not name it the same as above
TEMP_FILE_EXT = 'temp'
# Maximum characters in filename (excluding extension)
MAX_CHARACTERS = 20
end
#--------------------------------------------------------------------------
# * Get Memory remaining
#--------------------------------------------------------------------------
def get_memory
list = Dir.entries('.')
list.delete('.').delete('..').delete('Audio').delete('Graphics').delete('Data')
list.delete_if {|file| file.split('.')[-1] != FSBSS::SAVE_FILE_EXT}
megs = FSBSS::MAXIMUM_MEMORY
size = 0
list.each do |filename|
file = File.open(filename)
size += File.size(file) / 1024
file.close
end
megs *= 1024
megs -= size
return megs.to_i
end
#==============================================================================
# ** Window_SaveFile
#------------------------------------------------------------------------------
# This window displays save files on the save and load screens.
#==============================================================================
class Window_SaveFile < Window_Selectable
#--------------------------------------------------------------------------
# * Object Initialization
# loading : if window is used for loading
#--------------------------------------------------------------------------
def initialize(loading = false)
super(0, 96, 640, 416)
self.index = 0
self.opacity = 0
@loading = loading
refresh
end
#--------------------------------------------------------------------------
# * Get Save
#--------------------------------------------------------------------------
def save
return @data[self.index]
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
if self.contents != nil
self.contents.clear
self.contents = nil
end
@data = []
list = Dir.entries('.')
list.delete('.').delete('..').delete('Audio').delete('Graphics').delete('Data')
list.delete_if {|file| file.split('.')[-1] != FSBSS::SAVE_FILE_EXT}
@data = list << nil
@item_max = @data.size
self.contents = Bitmap.new(width - 32, @item_max * 32)
@data.each_index { |i| draw_save(i)}
end
#--------------------------------------------------------------------------
# * Draw Save
# index : save number
#--------------------------------------------------------------------------
def draw_save(index)
y = index * 32
filename = @data[index]
if filename
size = 0
file = File.open(filename)
size = File.size(file)
file.close
self.contents.draw_text(4, y, 300, 32, filename.split('.')[0])
self.contents.draw_text(304, y, 300, 32, "#{size / 1024} KB", 2)
else
self.contents.draw_text(4, y, 300, 32, '<Create New Data>')
end
end
#--------------------------------------------------------------------------
# * Help Text Update
#--------------------------------------------------------------------------
def update_help
text = @loading ? 'Load this file?' : 'Do what with this file?'
@help_window.set_text(save ? text : 'Create new data.')
end
end
#==============================================================================
# ** Window_SaveBar
#------------------------------------------------------------------------------
# This window displays the memory remaining and acts as a background to
# Window_SavfeFile.
#==============================================================================
class Window_SaveBar < Window_Base
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
super(0, 64, 640, 416)
self.contents = Bitmap.new(width - 32, height - 32)
refresh
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
self.contents.clear
self.contents.font.color = system_color
self.contents.draw_text(4, 0, 128, 32, '-Filename-')
self.contents.font.color = normal_color
self.contents.draw_text(132, 0, 472, 32,
"Remaining: #{get_memory} KB", 2)
end
end
#==============================================================================
# ** Window_Keyboard
#------------------------------------------------------------------------------
# This window displays characters to name savefiles.
#==============================================================================
class Window_Keyboard < Window_Selectable
CHARACTER_UPCASE =
[
"1","2","3","4","5","6","7","8","9","0",
"Q","W","E","R","T","Y","U","I","O","P",
"A","S","D","F","G","H","J","K","L","→",
"Z","X","C","V","B","N","M","↓","â†","_"
]
CHARACTER_DOWNCASE = [
"1","2","3","4","5","6","7","8","9","0",
"q","w","e","r","t","y","u","i","o","p",
"a","s","d","f","g","h","j","k","l","→",
"z","x","c","v","b","n","m","↑","â†","-"
]
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :upcase
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
super(0, 0, 640, 160)
self.contents = Bitmap.new(width - 32, height - 32)
self.index = 0
@item_max = CHARACTER_UPCASE.size
@column_max = 10
@upcase = false
refresh
end
#--------------------------------------------------------------------------
# * Get Character
#--------------------------------------------------------------------------
def character
table = @upcase ? CHARACTER_UPCASE : CHARACTER_DOWNCASE
return table[self.index]
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
self.contents.clear
table = @upcase ? CHARACTER_UPCASE : CHARACTER_DOWNCASE
table.each_index do |i|
x = i % 10 * 64
y = i / 10 * 32
self.contents.draw_text(x, y, 32, 32, table[i], 1)
end
end
end
#==============================================================================
# ** Window_FileName
#------------------------------------------------------------------------------
# This window displays the current filename when naming a savefile.
#==============================================================================
class Window_FileName < Window_Base
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_reader :name
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
super(0, 64, 640, 416)
self.contents = Bitmap.new(width - 32, height - 32)
@name = ''
refresh
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
self.contents.clear
self.contents.draw_text(4, 0, 600, 32, @name + '.' + FSBSS::SAVE_FILE_EXT, 1)
end
#--------------------------------------------------------------------------
# * Add character
# char : character
#--------------------------------------------------------------------------
def add(char)
if char == "â†"
delete
return
end
@name += char
refresh
end
#--------------------------------------------------------------------------
# * Delete Character
#--------------------------------------------------------------------------
def delete
string = @name.unpack('a' * @name.length)
string.pop
@name = string.to_s
refresh
end
#--------------------------------------------------------------------------
# * Clear
#--------------------------------------------------------------------------
def clear
@name = ''
refresh
end
end
#==============================================================================
# ** Scene_File
#------------------------------------------------------------------------------
# This is a superclass for the save screen and load screen.
#==============================================================================
class Scene_File
#--------------------------------------------------------------------------
# * Main Processing
#--------------------------------------------------------------------------
def main
@help_window = Window_Help.new
@save_window = Window_SaveFile.new($scene.is_a?(Scene_Load))
@savebar_window = Window_SaveBar.new
@save_window.help_window = @help_window
@keyboard_window = Window_Keyboard.new
@keyboard_window.x = 320 - @keyboard_window.width / 2
@keyboard_window.y = 272 - @keyboard_window.height / 2
@keyboard_window.visible = false
@keyboard_window.active = false
@filename_window = Window_FileName.new
@filename_window.visible = false
s1 = 'Overwrite'
s2 = 'Load'
s3 = 'Delete'
s4 = 'Cancel'
@save_command_window = Window_Command.new(160, [s1, s2, s3, s4])
@save_command_window.x = 320 - @save_command_window.width / 2
@save_command_window.y = 240 - @save_command_window.height / 2
@save_command_window.z += 10
@save_command_window.visible = false
@save_command_window.active = false
Graphics.transition
loop do
Graphics.update
Input.update
update
break if $scene != self
end
Graphics.freeze
@help_window.dispose
@save_window.dispose
@savebar_window.dispose
@keyboard_window.dispose
@filename_window.dispose
@save_command_window.dispose
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
@help_window.update
@save_window.update
@savebar_window.update
@keyboard_window.update
@filename_window.update
@save_command_window.update
if @save_window.active
update_save_window
elsif @keyboard_window.active
update_keyboard_window
elsif @save_command_window.active
update_save_command
end
end
#--------------------------------------------------------------------------
# * Frame Update - Save Window
#--------------------------------------------------------------------------
def update_save_window
if Input.trigger?(Input::C)
on_decision(@save_window.save)
return
end
if Input.trigger?(Input::B)
on_cancel
return
end
end
#--------------------------------------------------------------------------
# * Frame Update - Keyboard Window
#--------------------------------------------------------------------------
def update_keyboard_window
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
if @filename_window.name.length == 0
@save_window.visible = true
@save_window.active = true
@savebar_window.visible = true
@keyboard_window.visible = false
@filename_window.visible = false
@keyboard_window.active = false
return
end
@filename_window.delete
end
if Input.trigger?(Input::C)
if @keyboard_window.character == "→"
if @filename_window.name.length == 0
$game_system.se_play($data_system.buzzer_se)
@help_window.set_text('Cannot have a file with no name.')
return
end
if File.exist?(@filename_window.name + '.' + FSBSS::SAVE_FILE_EXT)
$game_system.se_play($data_system.buzzer_se)
@help_window.set_text('File already exists.')
return
end
file = File.new(@filename_window.name + '.' + FSBSS::SAVE_FILE_EXT, 'wb')
write_save_data(file)
file.close
if get_memory < 0
$game_system.se_play($data_system.buzzer_se)
File.delete(@filename_window.name + '.' + FSBSS::SAVE_FILE_EXT)
return
end
$game_system.se_play($data_system.save_se)
@save_window.visible = true
@save_window.active = true
@save_window.refresh
@savebar_window.refresh
@savebar_window.visible = true
@keyboard_window.visible = false
@filename_window.visible = false
@filename_window.clear
@keyboard_window.active = false
return
end
if @filename_window.name.length > FSBSS::MAX_CHARACTERS or
@keyboard_window.character == ""
$game_system.se_play($data_system.buzzer_se)
return
end
$game_system.se_play($data_system.decision_se)
if @keyboard_window.character == "↑"
@keyboard_window.upcase = true
@keyboard_window.refresh
return
end
if @keyboard_window.character == "↓"
@keyboard_window.upcase = false
@keyboard_window.refresh
return
end
@filename_window.add(@keyboard_window.character)
end
end
#--------------------------------------------------------------------------
# * Frame Update - Command Window
#--------------------------------------------------------------------------
def update_save_command
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@save_window.active = true
@save_command_window.visible = false
@save_command_window.active = false
return
end
if Input.trigger?(Input::C)
case @save_command_window.index
when 0 # Overwrite
old_file = @save_window.save.split('.')[0] + '.' + FSBSS::TEMP_FILE_EXT
File.rename(@save_window.save, old_file)
file = File.open(@save_window.save, "wb")
write_save_data(file)
file.close
if get_memory < 0
$game_system.se_play($data_system.buzzer_se)
File.delete(@save_window.save)
File.rename(old_file, @save_window.save)
@save_window.refresh
return
end
File.delete(old_file)
@save_window.refresh
@savebar_window.refresh
$game_system.se_play($data_system.save_se)
when 1 # Load
$game_system.se_play($data_system.load_se)
file = File.open(@save_window.save)
read_data(file)
file.close
$scene = Scene_Map.new
return
when 2 # Delete
$game_system.se_play($data_system.decision_se)
File.delete(@save_window.save)
@save_window.refresh
@savebar_window.refresh
when 3 # Cancel
$game_system.se_play($data_system.decision_se)
end
@save_window.active = true
@save_command_window.visible = false
@save_command_window.active = false
end
end
#--------------------------------------------------------------------------
# * Read Save Data
# file : file object for reading (opened)
#--------------------------------------------------------------------------
def read_data(file)
characters = Marshal.load(file)
Graphics.frame_count = Marshal.load(file)
$game_system = Marshal.load(file)
$game_switches = Marshal.load(file)
$game_variables = Marshal.load(file)
$game_self_switches = Marshal.load(file)
$game_screen = 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)
if $game_system.magic_number != $data_system.magic_number
$game_map.setup($game_map.map_id)
$game_player.center($game_player.x, $game_player.y)
end
$game_party.refresh
end
end
#==============================================================================
# ** Scene_Save
#------------------------------------------------------------------------------
# This class performs save screen processing.
#==============================================================================
class Scene_Save < Scene_File
#--------------------------------------------------------------------------
# * Decision Processing
#--------------------------------------------------------------------------
def on_decision(filename)
if filename.nil?
@save_window.active = false
@save_window.visible = false
@savebar_window.visible = false
@keyboard_window.active = true
@keyboard_window.visible = true
@filename_window.visible = true
return
end
@save_window.active = false
@save_command_window.visible = true
@save_command_window.index = 0
@save_command_window.active = true
return
end
#--------------------------------------------------------------------------
# * Cancel Processing
#--------------------------------------------------------------------------
def on_cancel
$game_system.se_play($data_system.cancel_se)
if $game_temp.save_calling
$game_temp.save_calling = false
$scene = Scene_Map.new
return
end
$scene = Scene_Menu.new(4)
end
end
#==============================================================================
# ** Scene_Load
#------------------------------------------------------------------------------
# This class performs load screen processing.
#==============================================================================
class Scene_Load < Scene_File
#--------------------------------------------------------------------------
# * Decision Processing
#--------------------------------------------------------------------------
def on_decision(filename)
if @save_window.save
$game_system.se_play($data_system.load_se)
file = File.open(@save_window.save)
read_save_data(file)
file.close
else
$game_system.se_play($data_system.decision_se)
command_new_game
end
$scene = Scene_Map.new
end
#--------------------------------------------------------------------------
# * Cancel Processing
#--------------------------------------------------------------------------
def on_cancel
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Title.new
end
#--------------------------------------------------------------------------
# * Read Save Data
# file : file object for reading (opened)
#--------------------------------------------------------------------------
alias read_save_data read_data
def read_save_data(file)
read_data(file)
end
#--------------------------------------------------------------------------
# * Command: New Game
#--------------------------------------------------------------------------
def command_new_game
temp = Scene_Title.new
temp.command_new_game
temp = nil
end
end
Instructions
- Insert this script below Scene_Debug. This is to assure that scripts that add to the save file are not messed up.
- Remove lines 48 to 52 in Scene_Title, change @continue_enabled = false[/FONT] to @continue_enabled = true[/FONT]
- Edit the constants in the FSBSS module to suit your needs.
FAQ
No questions asked
Compatibility
May be SDK compatible (conformation needed). Should be compatible with scripts that add to the save files.
Author's Notes
This script was originally developed for my game, Tropicana. I just thought I'd share it with you all.