#==============================================================================
# ☆★☆ Custom Save☆★☆
#------------------------------------------------------------------------------
# - FantasyDR
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# - 2006.7.18
#------------------------------------------------------------------------------
# 自定义存档数据排列顺序并校验存档
#==============================================================================
#==============================================================================
# ■ Scene_File
#------------------------------------------------------------------------------
# 存档画面及读档画面的超级类。
#==============================================================================
class Scene_File
#--------------------------------------------------------------------------
# ● 存档密钥,请定义成自己的密钥
# 密钥不同的存档将无法被读取
#--------------------------------------------------------------------------
SAVE_KEY = 1234567
#--------------------------------------------------------------------------
# ● 存档号码最大值
# 默认0~3共4个存档,如果需要大于4个存档,需要改动窗口类。
# 这里不提供大于4个存档的窗口排布,如果有需要请自己定义。
#--------------------------------------------------------------------------
SAVE_MAX = 3
#--------------------------------------------------------------------------
# ● 初始化对像
# help_text : 帮助窗口显示的字符串
#--------------------------------------------------------------------------
def initialize(help_text,type = "档案",save_max = SAVE_MAX)
@help_text = help_text
@save_max = save_max
@type = type
end
#--------------------------------------------------------------------------
# ● 主处理
#--------------------------------------------------------------------------
def main
# 生成存档选择
save_list = []
for i in 1..@save_max+1
save_list.push(@type+i.to_s)
end
# 生成帮助窗口
@help_window = Window_Help.new
@help_window.set_text(@help_text)
# 生成存档文件查
@savefile_windows = []
for i in 0..@save_max
@savefile_windows.push(Window_SaveFile.new(i, make_filename(i)))
end
# 选择最后操作的文件
@file_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
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 < 3
# 演奏光标 SE
$game_system.se_play($data_system.cursor_se)
# 光标向下移动
@savefile_windows[@file_index].selected = false
@file_index = (@file_index + 1) % 4
@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
@file_index = (@file_index + 3) % 4
@savefile_windows[@file_index].selected = true
return
end
end
end
#--------------------------------------------------------------------------
# ● 生成文件名
# file_index : 文件名的索引 (0~3)
#--------------------------------------------------------------------------
def make_filename(file_index)
return "Save#{file_index + 1}.rxdata"
end
end
#==============================================================================
# ■ Scene_Load
#------------------------------------------------------------------------------
# 处理读档画面的类。
#==============================================================================
class Scene_Load < Scene_File
#--------------------------------------------------------------------------
# ● 初始化对像
#--------------------------------------------------------------------------
def initialize(save_max = SAVE_MAX)
# 再生成临时对像
$game_temp = Game_Temp.new
# 选择存档时间最新的文件
$game_temp.last_file_index = 0
latest_time = Time.at(0)
for i in 0..save_max
filename = make_filename(i)
if FileTest.exist?(filename)
begin
file = Zlib::GzipReader.open(filename)
rescue
next
end
if file.mtime > latest_time
latest_time = file.mtime
$game_temp.last_file_index = i
end
file.close
end
end
super("要载入哪个文件?","读取",save_max)
end
#--------------------------------------------------------------------------
# ● 确定时的处理
#--------------------------------------------------------------------------
def on_decision(filename)
# 文件不存在的情况下
unless FileTest.exist?(filename)
# 演奏冻结 SE
$game_system.se_play($data_system.buzzer_se)
return
end
# 演奏读档 SE
$game_system.se_play($data_system.load_se)
# 写入存档数据
begin
file = Zlib::GzipReader.open(filename)
read_save_data(file)
rescue
# 演奏冻结 SE
$game_system.se_play($data_system.buzzer_se)
return
end
file.close
# 还原 BGM、BGS
$game_system.bgm_play($game_system.playing_bgm)
$game_system.bgs_play($game_system.playing_bgs)
# 刷新地图 (执行并行事件)
$game_map.update
# 切换到地图画面
$scene = Scene_Map.new
end
#--------------------------------------------------------------------------
# ● 取消时的处理
#--------------------------------------------------------------------------
def on_cancel
# 演奏取消 SE
$game_system.se_play($data_system.cancel_se)
# 切换到标题画面
$scene = Scene_Title.new
end
#--------------------------------------------------------------------------
# ● 读取存档数据
# file : 读取用文件对像 (已经打开)
#--------------------------------------------------------------------------
def read_save_data(file)
# 读取描绘存档文件用的角色数据
characters = Marshal.load(file)
# 读取测量游戏时间用画面计数
Graphics.frame_count = Marshal.load(file)
# 读取校验
crcs = Marshal.load(file)
# 读取文档字串
strings = Marshal.load(file)
# 校验检测
key = SAVE_KEY
strings.each_index do |i|
key = Zlib.crc32(strings[i],key)
unless crcs[i] == key
file.close
raise "file check error"
return
end
end
# 读取各种游戏对像
$game_system = Marshal.load(Zlib::Inflate.inflate(strings[0]))
$game_variables = Marshal.load(Zlib::Inflate.inflate(strings[1]))
$game_self_switches = Marshal.load(Zlib::Inflate.inflate(strings[2]))
$game_switches = Marshal.load(Zlib::Inflate.inflate(strings[3]))
$game_troop = Marshal.load(Zlib::Inflate.inflate(strings[4]))
$game_map = Marshal.load(Zlib::Inflate.inflate(strings[5]))
$game_player = Marshal.load(Zlib::Inflate.inflate(strings[6]))
$game_screen = Marshal.load(Zlib::Inflate.inflate(strings[7]))
$game_actors = Marshal.load(Zlib::Inflate.inflate(strings[8]))
$game_party = Marshal.load(Zlib::Inflate.inflate(strings[9]))
# 魔法编号与保存时有差异的情况下
# (加入编辑器的编辑过的数据)
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
#------------------------------------------------------------------------------
# 处理存档画面的类。
#==============================================================================
class Scene_Save < Scene_File
#--------------------------------------------------------------------------
# ● 初始化对像
#--------------------------------------------------------------------------
def initialize(save_max = SAVE_MAX)
super("要保存到这个文件吗?","存入",save_max)
end
#--------------------------------------------------------------------------
# ● 确定时的处理
#--------------------------------------------------------------------------
def on_decision(filename)
# 演奏存档 SE
$game_system.se_play($data_system.save_se)
# 写入存档数据
file = Zlib::GzipWriter.open(filename,9)
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(5)
end
#--------------------------------------------------------------------------
# ● 取消时的处理
#--------------------------------------------------------------------------
def on_cancel
# 演奏取消 SE
$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(5)
end
#--------------------------------------------------------------------------
# ● 写入存档数据
# file : 写入用文件对像 (已经打开)
#--------------------------------------------------------------------------
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,actor.id])
end
strings = []
# 写入描绘存档文件用的角色数据
Marshal.dump(characters,file)
# 写入测量游戏时间用画面计数
Marshal.dump(Graphics.frame_count,file)
# 增加 1 次存档次数
$game_system.save_count += 1
# 保存魔法编号
# (将编辑器保存的值以随机值替换)
$game_system.magic_number = $data_system.magic_number
# 写入各种游戏对像
strings.push(Zlib::Deflate.deflate(Marshal.dump($game_system)))
strings.push(Zlib::Deflate.deflate(Marshal.dump($game_variables)))
strings.push(Zlib::Deflate.deflate(Marshal.dump($game_self_switches)))
strings.push(Zlib::Deflate.deflate(Marshal.dump($game_switches)))
strings.push(Zlib::Deflate.deflate(Marshal.dump($game_troop)))
strings.push(Zlib::Deflate.deflate(Marshal.dump($game_map)))
strings.push(Zlib::Deflate.deflate(Marshal.dump($game_player)))
strings.push(Zlib::Deflate.deflate(Marshal.dump($game_screen)))
strings.push(Zlib::Deflate.deflate(Marshal.dump($game_actors)))
strings.push(Zlib::Deflate.deflate(Marshal.dump($game_party)))
# 计算校验值
crcs = []
key = SAVE_KEY
strings.each do |i|
key = Zlib.crc32(i,key)
crcs.push(key)
end
Marshal.dump(crcs,file)
Marshal.dump(strings,file)
end
end
#==============================================================================
# ■ Window_SaveFile
#------------------------------------------------------------------------------
# 显示存档以及读档画面、保存文件的窗口。
#==============================================================================
class Window_SaveFile < Window_Base
#--------------------------------------------------------------------------
# ● 初始化对像
# file_index : 存档文件的索引 (0~n)
# filename : 文件名
#--------------------------------------------------------------------------
def initialize(file_index, filename,viewport=nil)
super(0, 64 + file_index % 4 * 104, 640, 104)
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
begin
file = Zlib::GzipReader.open(filename)
@time_stamp = file.mtime
@characters = Marshal.load(file)
@frame_count = Marshal.load(file)
@total_sec = @frame_count / Graphics.frame_rate
file.close
rescue
@file_exist = false
end
end
self.refresh
@selected = false
end
end