Skip to content

Instantly share code, notes, and snippets.

@oott123
Created April 9, 2013 15:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oott123/5346768 to your computer and use it in GitHub Desktop.
Save oott123/5346768 to your computer and use it in GitHub Desktop.
#==============================================================================
# 〇 GAL用存读档界面 2.1
#
# 2.1 by orzFly.com
# 回滚为老版本 YesNoBox~好看!
# 标题调用时有单独背景图
# 可以隐藏掉那个坑爹的“旧的回忆”标题
# 可以透明化窗口用自己的背景
# 修正 bug:删不掉存档……
#
# 2.0 by orzFly.com
# 整理脚本结构
# 扩展为无限,增加详细信息、小列表
#
# 1.1 by 各种压力的猫君
# 集成了一箭烂的删除存档1.1
#
# 1.0 by 各种压力的猫君
# 初版
#
# 参考脚本 R剧用的存读档界面 by 冰舞蝶恋
# 删除存档v1.1.0 by 一箭烂(YiJL)
# Neo Save System III by Woratana [woratana@hotmail.com]
#------------------------------------------------------------------------------
# 脚本说明:
#
#  本人脚本盲,只会改不会写,所以需要改进的话
#  请联系各位脚本大神而不是我[各种压力的猫君] =-= |||
#------------------------------------------------------------------------------
module GALSave
#==============================================================================
# ▼ 脚本修改 *建议* 从此开始。
#==============================================================================
# 存档个数 : 请按情况填写。填写过多也不会导致加载过慢。
MaxSaveSlot = 100
# 存档位置 : 请填写储存存档文件的位置。
# RMVX 的默认位置为 "",
# 由于存档个数的提升,默认位置已不再优雅。
# 附注:您无需预先建立与分发此文件夹,脚本会自动建立。
SavePath = "Saves/"
# 存档文件名 : 请填写存档文件的文件名模板。
# 存档号请用 {id} 代替。
# 衬 0 的存档号请用 {ID} 代替。
SaveName = "Save{ID}.rvdata"
# 场景名队伍 ID
SceneNameID = 2
# 章节名队伍 ID
ChapterNameID= 3
# 界面标题 :留空就可以让他坑爹掉~
# 但是请注意要留住引号,否则脚本会报错。
ScreenTitle = ""
# 窗口透明度 : 设置成 0 就让窗口背景消失了
Opacity = 255
# 视图 : 请填写使用的视图 ID。
#
# 可用的视图 ID:
# 0 - 小列表
# 1 - 大列表
View = 1
# 边距大小(左右上下)
MarginLeft = 32
MarginRight = 32
MarginTop = 20
MarginBottom = 20
# 存档名称 : 模板规则同 SaveName 存档文件名
SlotName = '存档 {id}'
# 存档图标
SavedSlotIcon= 133 # 满
EmptySlotIcon= 141 # 空
# 空存档文字
EmptySlotText= '- 无数据 -'
# 大图标字段名
PlayTimeText = '时长: '
SaveTimeText = '时间: '
SceneText = '场景: '
ChapterText = '章节: '
# 允许删除
AllowDelete = true
# 删除提示 : 模板规则同 SaveName 存档文件名
DeletePrompt = "确认删除存档 {id}?"
DeleteButton = ["删除", "取消"]
# 覆盖提示
Overwrite = true
# 覆盖提示 : 模板规则同 SaveName 存档文件名
OverwritePrompt = "确认覆盖存档 {id}?"
OverwriteButton = ["覆盖", "取消"]
# 读档背景 : 从标题读档时可以有背景图。
# 写 Cache.picture('文件名') 就为 Pictures 目录下的图片
# 也可以写 nil 用默认的透明化标题菜单~
LoadBackground = nil
# 菜单背景 : 用一张透明的全屏 PNG 来实现深度自定义档位外观吧!
# 请配合 Opacity 使用!
# 写 Cache.picture('文件名') 就为 Pictures 目录下的图片
# 也可以写 nil 不使用。
MenuBackground = nil
#==============================================================================
# ▲ 脚本修改 *建议* 到此为 *止*。
#==============================================================================
#--------------------------------------------------------------------------
# ● 字符串模板
#--------------------------------------------------------------------------
def self.string_template(str, id)
name = str.clone
name.gsub!(/\{id\}/) { id.to_s }
name.gsub!(/\{ID\}/) { id.is_a?(String) ? id : sprintf("%0#{GALSave::MaxSaveSlot.to_s.size}d", id) }
return name
end
#--------------------------------------------------------------------------
# ● 创建存档文件名
#--------------------------------------------------------------------------
def self.make_filename(id)
return string_template(GALSave::SavePath + GALSave::SaveName, id)
return name
end
#--------------------------------------------------------------------------
# ● 创建存档名
#--------------------------------------------------------------------------
def self.make_slotname(id)
return string_template(GALSave::SlotName, id)
end
end
#==============================================================================
# ■ Game_GALSave
#------------------------------------------------------------------------------
#  为加快存档界面反应速度特加入此类。
#  应用在 Scene_File 内部
#==============================================================================
class Game_GALSave
#--------------------------------------------------------------------------
# ● 初始化
#--------------------------------------------------------------------------
def initialize()
# 为存档创建文件夹
Dir.mkdir(GALSave::SavePath) if GALSave::SavePath != '' and !FileTest.directory?(GALSave::SavePath)
# 初始化存档缓存
@saves = []
end
#--------------------------------------------------------------------------
# ● 检查存档是否存在
#--------------------------------------------------------------------------
def exist?(id)
return Dir.glob(GALSave.make_filename(id)).size > 0 if id.is_a?(String)
return FileTest.exist?(GALSave.make_filename(id))
end
#--------------------------------------------------------------------------
# ● 加载存档信息
#--------------------------------------------------------------------------
def load_info(id)
return if id.is_a?(String)
return unless exist?(id)
file = File.open(GALSave.make_filename(id), "r")
begin
info = []
info[0] = file.mtime
info[1] = Marshal.load(file)
info[2] = Marshal.load(file) / Graphics.frame_rate
Marshal.load(file)
Marshal.load(file)
Marshal.load(file)
Marshal.load(file)
Marshal.load(file)
info[3] = Marshal.load(file)
ensure
file.close
end
@saves[id] = info
end
#--------------------------------------------------------------------------
# ● 获取存档信息
#--------------------------------------------------------------------------
def [](id)
return nil if id.is_a?(String)
if exist?(id)
load_info(id) if @saves[id].nil? or (File.mtime(GALSave.make_filename(id)) > @saves[id][0])
else
@saves[id] = nil
end
return @saves[id]
end
#--------------------------------------------------------------------------
# ● 获取最新存档
#--------------------------------------------------------------------------
def latest_file
id = 1
time = nil
GALSave::MaxSaveSlot.times {|i|
if exist?(i + 1)
t = File.mtime(GALSave.make_filename(i + 1))
time = t if time.nil?
if t > time
id = i + 1
time = t
end
end
}
return id
end
end
#==============================================================================
# ■ Window_GALSave
#------------------------------------------------------------------------------
#  显示神奇的 GAL 特有的存档窗口~
#==============================================================================
class Window_GALSave < Window_Selectable
#--------------------------------------------------------------------------
# ● 初始化目标
# x : 窗口的X坐标
# y : 窗口的Y坐标
#--------------------------------------------------------------------------
def initialize
@item_height = GALSave::View == 0 ? WLH : WLH * 3
super(
GALSave::MarginLeft,
GALSave::MarginTop + (GALSave::ScreenTitle != "" ? WLH + 32 : 0),
Graphics.width - GALSave::MarginLeft - GALSave::MarginRight,
Graphics.height - GALSave::MarginTop - GALSave::MarginBottom - (GALSave::ScreenTitle != "" ? WLH + 32 : 0)
)
self.opacity = GALSave::Opacity
@loaded = []
refresh
end
#--------------------------------------------------------------------------
# ● 刷新
#--------------------------------------------------------------------------
def refresh
self.contents.clear
@item_max = GALSave::MaxSaveSlot
create_contents
self.top_row = 0
end
#--------------------------------------------------------------------------
# ● 刷新画面
#--------------------------------------------------------------------------
def update
if cursor_movable?
last_index = @index
if Input.repeat?(Input::RIGHT)
cursor_pagedown
end
if Input.repeat?(Input::LEFT)
cursor_pageup
end
if @index != last_index
Sound.play_cursor
end
end
super
end
#--------------------------------------------------------------------------
# ● 绘制行
#--------------------------------------------------------------------------
def draw_item(i)
rect = item_rect(i)
self.contents.clear_rect(rect)
rect.x += 4
exist = $game_galsave.exist?(i + 1)
icon = exist ? GALSave::SavedSlotIcon : GALSave::EmptySlotIcon
unless icon.nil?; rect.x -= 4; draw_icon(icon, rect.x, rect.y); rect.x += 26; rect.width -= 20; end
width = contents.text_size(GALSave.make_slotname(GALSave::MaxSaveSlot)).width
self.contents.draw_text(rect.x, rect.y, width, WLH, GALSave.make_slotname(i + 1)); rect.x += width + 4; rect.width -= width + 4
if exist
time = $game_galsave[i + 1][0].strftime("%m.%d(%H:%M)")
# scene = $game_galsave[i + 1][1][GALSave::SceneNameID - 1][2]
scene = $game_galsave[i + 1][3][0]
#变量0是场景名
# chapter = $game_galsave[i + 1][1][GALSave::ChapterNameID - 1][2]
chapter = $game_galsave[i + 1][3][1]
#变量1是章节名
hour = $game_galsave[i + 1][2] / 60 / 60
min = $game_galsave[i + 1][2] / 60 % 60
sec = $game_galsave[i + 1][2] % 60
long = sprintf("%04d:%02d:%02d", hour, min, sec)
end
if GALSave::View == 0
if !exist
self.contents.draw_text(rect, GALSave::EmptySlotText, 1)
else
self.contents.font.size /= 2
width = [contents.text_size(long).width, contents.text_size(time).width].max
self.contents.draw_text(rect.x, rect.y, width, WLH / 2, time, 1)
self.contents.draw_text(rect.x, rect.y + WLH / 2, width, WLH / 2, long, 1)
rect.x += width + 4; rect.width -= width + 4
self.contents.font.size = Font.default_size
self.contents.draw_text(rect.x, rect.y, rect.width / 2, rect.height, chapter, 1)
self.contents.draw_text(rect.x + rect.width / 2, rect.y, rect.width / 2, rect.height, scene, 1)
end
else GALSave::View == 1
if !exist
self.contents.draw_text(rect, GALSave::EmptySlotText, 1)
else
width = rect.width / 2
w = contents.text_size(GALSave::PlayTimeText).width
self.contents.font.color = system_color
self.contents.draw_text(rect.x, rect.y, w, WLH, GALSave::PlayTimeText)
self.contents.font.color = normal_color
self.contents.draw_text(rect.x + w, rect.y, width - w, WLH, long)
w = contents.text_size(GALSave::SaveTimeText).width
self.contents.font.color = system_color
self.contents.draw_text(rect.x + width, rect.y, w, WLH, GALSave::SaveTimeText)
self.contents.font.color = normal_color
self.contents.draw_text(rect.x + width + w, rect.y, width - w, WLH, time)
width = rect.width
rect.y += WLH
w = contents.text_size(GALSave::ChapterText).width
self.contents.font.color = system_color
self.contents.draw_text(rect.x, rect.y, w, WLH, GALSave::ChapterText)
self.contents.font.color = normal_color
self.contents.draw_text(rect.x+ w, rect.y, width - w, WLH, chapter)
rect.y += WLH
w = contents.text_size(GALSave::SceneText).width
self.contents.font.color = system_color
self.contents.draw_text(rect.x, rect.y, w, WLH, GALSave::SceneText)
self.contents.font.color = normal_color
self.contents.draw_text(rect.x+w, rect.y, width - w, WLH, scene)
end
end
end
#--------------------------------------------------------------------------
# ● 窗口内容生成
#--------------------------------------------------------------------------
def create_contents
self.contents.dispose
self.contents = Bitmap.new(width - 32, [height - 32, row_max * @item_height].max)
end
#--------------------------------------------------------------------------
# ● 获取开头行
#--------------------------------------------------------------------------
def top_row(oy = nil)
return (oy.nil? ? self.oy : oy) / @item_height
end
#--------------------------------------------------------------------------
# ● 设置开头行
# row : 显示开头的行
#--------------------------------------------------------------------------
# 为保证高速,只在显示到某行的时候才加载、绘制行。
#--------------------------------------------------------------------------
def top_row=(row)
row = 0 if row < 0
row = row_max - 1 if row > row_max - 1
min = self.top_row(row * @item_height)
max = [min + self.page_item_max + 1, @item_max].min
for i in min...max
if @loaded[i].nil?
@loaded[i] = true
draw_item(i)
end
end
self.oy = row * @item_height
end
#--------------------------------------------------------------------------
# ● 获取 1 页可以显示的行数
#--------------------------------------------------------------------------
def page_row_max
return (self.height - 32) / @item_height
end
#--------------------------------------------------------------------------
# ● 获取项目描画矩形
# index : 项目编号
#--------------------------------------------------------------------------
def item_rect(index)
rect = Rect.new(0, 0, 0, 0)
rect.width = (contents.width + @spacing) / @column_max - @spacing
rect.height = @item_height
rect.x = index % @column_max * (rect.width + @spacing)
rect.y = index / @column_max * @item_height
return rect
end
end
#==============================================================================
# ■ Window_GALSave_Title
#------------------------------------------------------------------------------
#  显示读档或是存档的标题。
#==============================================================================
class Window_GALSave_Title < Window_Base
#--------------------------------------------------------------------------
# ● 初始化对像
#--------------------------------------------------------------------------
def initialize
super(
GALSave::MarginLeft,
GALSave::MarginTop,
(Graphics.width - GALSave::MarginLeft - GALSave::MarginRight) / 2,
WLH + 32
)
self.opacity = GALSave::Opacity
refresh
end
#--------------------------------------------------------------------------
# ● 刷新
#--------------------------------------------------------------------------
def refresh
self.contents.clear
self.contents.font.color = normal_color
self.contents.font.bold = true
self.contents.draw_text(0, 0, 220, WLH, GALSave::ScreenTitle)
end
end
#==============================================================================
# ■ Scene_File
#------------------------------------------------------------------------------
#  存档画面及读档画面的类。
#==============================================================================
class Scene_File
#--------------------------------------------------------------------------
# ● 开始处理
#--------------------------------------------------------------------------
def start
super
create_menu_background
unless GALSave::MenuBackground.nil?
@background = Sprite.new
@background.x, @background.y = 0, 0
@background.bitmap = GALSave::MenuBackground
end
$game_galsave = Game_GALSave.new if $game_galsave.nil?
@save_window = Window_GALSave.new
@title_window = Window_GALSave_Title.new unless GALSave::ScreenTitle == ""
if @saving
@save_window.index = $game_temp.last_file_index
else
@save_window.index = $game_galsave.latest_file - 1
end
end
#--------------------------------------------------------------------------
# ● 刷新菜单画面背景
#--------------------------------------------------------------------------
def update_menu_background
super
return unless @from_title
@menuback_sprite.bitmap = GALSave::LoadBackground unless GALSave::LoadBackground.nil?
end
#--------------------------------------------------------------------------
# ● 结束处理
#--------------------------------------------------------------------------
def terminate
super
dispose_menu_background
@save_window.dispose
@title_window.dispose unless GALSave::ScreenTitle == ""
@background.dispose unless GALSave::MenuBackground.nil?
end
#--------------------------------------------------------------------------
# ● 更新画面
#--------------------------------------------------------------------------
def update
super
update_menu_background
update_savefile_selection
@title_window.update unless GALSave::ScreenTitle == ""
@save_window.update
@background.update unless GALSave::MenuBackground.nil?
end
#--------------------------------------------------------------------------
# ● 刷新存档文件选项
#--------------------------------------------------------------------------
def update_savefile_selection
if Input.trigger?(Input::C)
determine_savefile
elsif Input.trigger?(Input::X) and GALSave::AllowDelete
determine_deletefile
elsif Input.trigger?(Input::B)
Sound.play_cancel
return_scene
end
end
#--------------------------------------------------------------------------
# ● 决定存档文件
#--------------------------------------------------------------------------
def determine_savefile
if @saving
if $game_galsave.exist?(@save_window.index + 1) and GALSave::Overwrite
Sound.play_decision
return if !yesnobox(GALSave.string_template(GALSave::OverwritePrompt, @save_window.index + 1), *GALSave::OverwriteButton)
end
Sound.play_save
do_save
else
if $game_galsave.exist?(@save_window.index + 1)
Sound.play_load
do_load
else
Sound.play_buzzer
return
end
end
$game_temp.last_file_index = @save_window.index
end
#--------------------------------------------------------------------------
# ● 决定删除文件
#--------------------------------------------------------------------------
def determine_deletefile
if $game_galsave.exist?(@save_window.index + 1)
Sound.play_decision
do_delete if yesnobox(GALSave.string_template(GALSave::DeletePrompt, @save_window.index + 1), *GALSave::DeleteButton)
return
else
Sound.play_buzzer
return
end
end
#--------------------------------------------------------------------------
# ● 执行删除
#--------------------------------------------------------------------------
def do_delete
File.delete(GALSave.make_filename(@save_window.index + 1))
@save_window.draw_item(@save_window.index)
end
#--------------------------------------------------------------------------
# ● 执行保存
#--------------------------------------------------------------------------
def do_save
file = File.open(GALSave.make_filename(@save_window.index + 1), "wb")
write_save_data(file)
file.close
return_scene
end
#--------------------------------------------------------------------------
# ● 执行读取
#--------------------------------------------------------------------------
def do_load
file = File.open(GALSave.make_filename(@save_window.index + 1), "rb")
read_save_data(file)
file.close
$scene = Scene_Map.new
RPG::BGM.fade(1500)
Graphics.fadeout(60)
Graphics.wait(40)
@last_bgm.play
@last_bgs.play
end
#--------------------------------------------------------------------------
# ● 存档数据的写入
# file : 写入用文件对象 (已打开)
#--------------------------------------------------------------------------
def write_save_data(file)
characters = []
for actor in $game_party.members
characters.push([actor.character_name, actor.character_index, actor.name])
end
$game_system.save_count += 1
$game_system.version_id = $data_system.version_id
@last_bgm = RPG::BGM::last
@last_bgs = RPG::BGS::last
Marshal.dump(characters, file)
Marshal.dump(Graphics.frame_count, file)
Marshal.dump(@last_bgm, file)
Marshal.dump(@last_bgs, file)
Marshal.dump($game_system, file)
Marshal.dump($game_message, file)
Marshal.dump($game_switches, file)
Marshal.dump($game_variables, file)
Marshal.dump($game_self_switches, 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
#--------------------------------------------------------------------------
# ● 确认对话框
#--------------------------------------------------------------------------
def yesnobox(text,yes,no)
returnval = false
command_window = Window_YesNoBox.new(text, yes, no)
command_window.z = 9999
command_window.openness = 0
command_window.open
for i in 0...9
command_window.update
Graphics.update
end
loop do
command_window.update
Graphics.update
Input.update
if Input.trigger?(Input::C)
Sound.play_decision
returnval = command_window.index == 0 ? true : false
break
end
if Input.trigger?(Input::B)
Sound.play_cancel
returnval = false
break
end
end
command_window.close
for i in 0...9
command_window.update
Graphics.update
end
command_window.dispose
Graphics.update
Input.update
return returnval
end
end
#==============================================================================
# ■ Window_YesNoBox
#==============================================================================
class Window_YesNoBox < Window_Selectable
#--------------------------------------------------------------------------
# ● 对象初始化
#--------------------------------------------------------------------------
def initialize(words, yes, no)
super((Graphics.width - 230)/2, (Graphics.height - 80)/2, 230, 80)
self.contents.font.size = 20
self.contents.font.color = system_color
self.contents.draw_text(0, 0, 200, 24, words, 1)
self.contents.font.size = 18
self.contents.font.color = normal_color
self.contents.draw_text(14, 24, 70, 24, yes, 1)
self.contents.draw_text(114, 24, 70, 24, no, 1)
@item_max = 2
@column_max = 2
@index = 0
end
#--------------------------------------------------------------------------
# ● 帧更新
#--------------------------------------------------------------------------
def update
super
if self.visible
if cursor_movable?
last_index = @index
if Input.repeat?(Input::DOWN)
cursor_down(Input.trigger?(Input::DOWN))
end
if Input.repeat?(Input::UP)
cursor_up(Input.trigger?(Input::UP))
end
if @index != last_index
Sound.play_cursor
end
end
update_cursor
call_update_help
end
end
#--------------------------------------------------------------------------
# ● 选择矩形
#--------------------------------------------------------------------------
def item_rect(index)
rect = Rect.new(0, 0, 0, 0)
rect.width = (contents.width + 5) / @column_max - 5
rect.height = WLH
rect.x = index % @column_max * (rect.width + 5)
rect.y = index / @column_max * WLH + 24
return rect
end
end
#==============================================================================
# ■ 标题画面检查存档
#==============================================================================
class Scene_Title < Scene_Base
def check_continue
$game_galsave = Game_GALSave.new if $game_galsave.nil?
@continue_enabled = $game_galsave.exist?("*")
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment