#------------------------------------------------------------------------
# Menu Sauvegarde améliorée
# RPG Maker VX
#
# Auteur : Samarium
#
# Créé le 15 Mai 2008
#
#
# Fonction : Permet d'améliorer le menu sauvegarde. Il est possible de supprimer
# une sauvegarde. Un message de confirmation pour remplacer
# ou effacer est présent aussi.
#
#
# Site du créateur : www.rpgcreative.net
#
# Remarque : script disponible aussi sous RPG Maker XP
#
#------- Modification ---------
#
#------------------------------------------------------------------------
$fontface = "Arial"
$fontsize =24
module AM_SAVE
#--------------------------------------------------------
# Définissez les images
#--------------------------------------------------------
GAUGE_EXP = "015-Greens01" # Image pour la gauge d'expérience
GAUGE_HP = "014-Reds01" # Image pour la gauge de points de vie
GAUGE_SP = "013-Blues01" # Image pour la gauge de poins de magie
FOND_GAUGE = "Back2" # Fond des jauges
WINDOWSKIN_BIS = "Window01" # Windowskin lorsqu'il y a un slot utilisé
FOND = "fond_save" # Arrière plan
# La constante ci-dessous permet d'inverser les windowskins. Si vous mettez
# "true", le "WINDOWSKIN_BIS" de ci-dessus sera appliqué seulement aux slots
# de sauvegardes vides. Sinon, si vous mettez "false", ça sera le windowskin par défaut
# qui sera appliqué aux slot vides
INVERSE_WINDOWSKIN = false
# Windowskin par défaut
WINDOWSKIN_DEFAUT = "Window"
end
#--------------------------------------------------------
# Module Files (Créé par Samarium)
# Ce module permettra de prendre toutes les
# données du fichier rvdata
#--------------------------------------------------------
module Files
class Donnees
# Index du fichier
attr_accessor :file_index
# Donnée de la classe File
attr_reader :time_stamp
# Données du fichier rvdata
attr_reader :characters
attr_reader :frame_count
attr_reader :last_bgm
attr_reader :last_bgs
attr_reader :system
attr_reader :switches
attr_reader :variables
attr_reader :self_switches
attr_reader :screen
attr_reader :actors
attr_reader :party
attr_reader :troop
attr_reader :map
attr_reader :player
def initialize(file_index = 0)
@file_index = file_index
if exist?
file = File.open(filename, "r")
@time_stamp = file.mtime
@characters = Marshal.load(file)
@frame_count = Marshal.load(file)
@last_bgm = Marshal.load(file)
@last_bgs = Marshal.load(file)
@system = Marshal.load(file)
@switches = Marshal.load(file)
@variables = Marshal.load(file)
@self_switches = Marshal.load(file)
@screen = Marshal.load(file)
@actors = Marshal.load(file)
@party = Marshal.load(file)
@troop = Marshal.load(file)
@map = Marshal.load(file)
@player = Marshal.load(file)
file.close
end
end
def exist?
return FileTest.exist?(filename)
end
def filename
return "Save#{file_index + 1}.rvdata"
end
end
end
#--------------------------------------------------------
# Window_SaveFile modifié
# Les fenêtres pour les slots
#--------------------------------------------------------
class Window_SaveFile < Window_Base
attr_reader :selected
def initialize(file_index, filename = nil)
super(15, 60 + file_index % 4 * 85, 115, 70)
self.contents = Bitmap.new(width - 32 , height - 32)
self.contents.font.name = $fontface
@opacity = 80
self.opacity = @opacity
@file_index = file_index
# Charge les données du fichier.
@game = Files::Donnees.new(file_index)
refresh
@selected = false
end
def refresh
self.contents.clear
self.contents.font.size = 18
name = "Slot #{@file_index + 1}"
# self.contents.font.color = normal_color
# name = "File #{@file_index + 1}"
self.contents.draw_text(0, 0, 600, 32, name)
# Si il y a déjà une sauvegarde
if @game.exist?
@game = Files::Donnees.new(@file_index)
windowskin = AM_SAVE::INVERSE_WINDOWSKIN ? AM_SAVE::WINDOWSKIN_BIS : AM_SAVE::WINDOWSKIN_DEFAUT
self.windowskin = Cache.system(windowskin)
text = @game.time_stamp.strftime("%d/%m/%Y %H:%M")
else
windowskin = AM_SAVE::INVERSE_WINDOWSKIN ? AM_SAVE::WINDOWSKIN_DEFAUT : AM_SAVE::WINDOWSKIN_BIS
self.windowskin = Cache.system(windowskin)
text = "Vide"
end
self.contents.font.size = 13
# self.contents.font.color = normal_color
self.contents.draw_text(0, 17, 600, 32, text)
end
def selected=(selected)
@selected = selected
update_cursor_rect
end
# Défini l'opacité et positionnement du slot lorsque ce dernier est sélectionné
def update_cursor_rect
if @selected
self.opacity = 255
self.x = 30
else
self.opacity = @opacity
self.x = 15
end
end
end
#--------------------------------------------------------
# Window_SaveStatus
# Fenêtre avec les indications des héros (PV, MP ...)
#--------------------------------------------------------
# (0, 0, 544, 416)
class Window_FileStatus < Window_Base
def initialize
super(640, 60, 360, 270)
self.contents = Bitmap.new(width - 32, height - 32)
self.contents.font.name = $fontface
self.contents.font.size = 15
self.opacity = 150
refresh
end
def refresh(file_index=0)
self.contents.clear
@game = Files::Donnees.new(file_index)
if @game.exist?
# Affiche en boucle les héros
for i in 0...@game.characters.size
# Algorithme pour afficher 2 héros sur 2 colonnes
x = i < 2 ? 32 : 200
j = (i == 2 or i == 0) ? 0 : j+1
y = j * 130
# Affichage des caractéristiques
actor = @game.party.members[i]
draw_actor_name(actor, x, y)
draw_actor_graphic(actor, x - 20, y + 80)
# draw_actor_class(actor, x + 144, y)
draw_actor_level(actor, x, y + 16)
draw_actor_state(actor, x + 60, y + 16)
draw_actor_exp(actor, x, y + 40)
draw_actor_hp(actor, x , y + 60)
draw_actor_mp(actor, x, y + 80)
end
end
end
# Permet de faire bouger vers la gauche la fenêtre
def bouger
self.x -= 40 if self.x >= 175 if @game.exist?
return true if self.x <= 175
end
# permet de retirer la fenêtre de l'écran
def retirer
self.x += 40 if self.x <= 575 if @game.exist?
return true if self.x >= 575
end
# Déssine une jauge
def draw_gauge(x, y, min, max, file, width, height)
pourcentage = max == 0 ? 0 : min.to_f / max.to_f
gauge = Cache.picture(file)
fond = Cache.picture(AM_SAVE::FOND_GAUGE)
gauge_dest = Rect.new(x, y, width * pourcentage, gauge.height)
fond_dest = Rect.new(x, y,width, fond.height)
gauge_source = Rect.new(0,0, gauge.width, gauge.height)
fond_source = Rect.new(0,0, fond.width,fond.height)
self.contents.stretch_blt(fond_dest, fond, fond_source)
self.contents.stretch_blt(gauge_dest, gauge, gauge_source)
end
# Reprise de la méthode de Window_Base en affichant la jauge d'expérience
def draw_actor_exp(actor, x, y)
min = actor.level == 99 ? 1 : actor.exp_s
max = actor.level == 99 ? 1 : actor.next_exp_s
draw_gauge(x + 32, y + 16, min, max,AM_SAVE::GAUGE_EXP, 80,
if actor.level == 99
self.contents.draw_text(x + 33, y, 600, 32, "-----/-----")
else
self.contents.draw_text(x + 33, y, 600, 32, min.to_s + "/" + max.to_s)
end
self.contents.font.color = system_color
self.contents.draw_text(x, y, 32, 32, "Exp")
end
# Reprise de la méthode de Window_Base en affichant la jauge de PV
def draw_actor_hp(actor, x, y, width=144)
draw_gauge(x + 32, y + 16,actor.hp , actor.maxhp,AM_SAVE::GAUGE_HP, 80,
self.contents.font.color = system_color
self.contents.draw_text(x, y, 32, 32, Vocab::hp_a)
if width - 32 >= 108
hp_x = x + width - 138
flag = true
elsif width - 32 >= 48
hp_x = x + width - 88
flag = false
end
self.contents.font.color = actor.hp == 0 ? knockout_color :
actor.hp <= actor.maxhp / 4 ? crisis_color : normal_color
self.contents.draw_text(hp_x, y, 48, 32, actor.hp.to_s, 2)
if flag
self.contents.font.color = normal_color
self.contents.draw_text(hp_x + 48, y, 12, 32, "/", 1)
self.contents.draw_text(hp_x + 60, y, 48, 32, actor.maxhp.to_s)
end
end
# Reprise de la méthode de Window_Base en affichant la jauge de MP
def draw_actor_mp(actor, x, y, width = 144)
draw_gauge(x + 32, y + 16,actor.mp , actor.maxmp,AM_SAVE::GAUGE_SP, 80,
self.contents.font.color = system_color
self.contents.draw_text(x, y, 32, 32, Vocab::mp_a)
if width - 32 >= 108
sp_x = x + width - 138
flag = true
elsif width - 32 >= 48
sp_x = x + width - 88
flag = false
end
self.contents.font.color = actor.mp == 0 ? knockout_color :
actor.mp <= actor.maxmp / 4 ? crisis_color : normal_color
self.contents.draw_text(sp_x, y, 48, 32, actor.mp.to_s, 2)
if flag
self.contents.font.color = normal_color
self.contents.draw_text(sp_x + 48, y, 12, 32, "/", 1)
self.contents.draw_text(sp_x + 60, y, 48, 32, actor.maxmp.to_s)
end
end
end
#--------------------------------------------------------
# Window_FileInfo
# Fenêtre avec les infos du jeu en bas de l'écran
#--------------------------------------------------------
class Window_FileInfo < Window_Base
def initialize
super(640, 337, 360, 75)
self.contents = Bitmap.new(width - 32, height - 32 )
self.contents.font.name = $fontface
self.contents.font.color = normal_color
self.opacity = 150
refresh
end
def refresh(file_index = 0)
self.contents.clear
@game = Files::Donnees.new(file_index)
if @game.exist?
self.contents.font.size = 15
@total_sec = @game.frame_count / Graphics.frame_rate
cx = contents.text_size(Vocab::gold).width
cgold = contents.text_size(@game.party.gold.to_s).width
# Affiche argent possédé, sauvegardes effetués et temps joué
self.contents.draw_text(4, 0, 130, 32, "Argent possédé :")
self.contents.draw_text(110, 0, 120-cx-2, 32, @game.party.gold.to_s)
self.contents.draw_text(112 + cgold, 0, cx, 32, Vocab::gold)
self.contents.draw_text(200, 0, 300, 32, "Sauvegardes : " + @game.system.save_count.to_s)
hour = @total_sec / 60 / 60
min = @total_sec / 60 % 60
sec = @total_sec % 60
time_string = sprintf("%02d:%02d:%02d", hour, min, sec)
self.contents.draw_text(4, 10, 100, 32, "Temps joué : ")
self.contents.draw_text(110, 10, 100, 32, time_string)
self.contents.font.size = 13
self.contents.draw_text(45, 25, 250, 25, "Appuyez sur SHIFT pour effacer une sauvegarde")
end
end
# permet de faire bouger la fenêtre vers le haut
def bouger
self.x -= 40 if self.x >= 175 if @game.exist?
end
end
#--------------------------------------------------------
# Window_FileConfirm
# Fenêtre pour les confirmations
#--------------------------------------------------------
class Window_FileConfirm < Window_Selectable
attr_reader :type
def initialize
super(640, 140, 360, 120)
self.contents = Bitmap.new(width - 32, height - 32)
self.contents.font.name = $fontface
self.contents.font.size = 18
refresh
self.active = false
self.opacity = 150
@type = 0
end
# Affiche des phrases de confirmation selon le type choisit
def refresh(type = 0)
self.contents.clear
@type = type
self.index = 1
if type == 0
self.contents.draw_text(65, 0, 410, 32, "Il existe déjà une sauvegarde", 0)
self.contents.draw_text(25, 25, 300, 32, "Etes vous sûr de la remplacer ?", 1)
elsif type == 1
self.contents.draw_text(25, 20, 300, 32, "Etes vous sûr de la supprimer ?", 1)
elsif type == 2
self.index = -1
self.contents.draw_text(52, 20, 400, 32, "Le fichier a été supprimé avec succès")
elsif type == 3 or type == 4
self.index = -1
self.contents.draw_text(60, 20, 400, 32, "Jeu sauvegardé avec succès")
end
# Sélection du "Oui" ou "Non"
if type != 2 and type != 3 and type != 4
self.contents.draw_text(100, 60, 50, 32, "Oui", 1)
self.contents.draw_text(200, 60, 50, 32, "Non", 1)
end
end
def update_cursor
if @index < 0
self.cursor_rect.empty
else
self.cursor_rect.set(100 * @index, 60, 50, 32)
end
end
# Bouge la fenêtre vers la gauche
def bouger
self.x -= 40 if self.x >= 175
return true if self.x <= 175
end
# Retire la fenêtre
def retirer
self.x += 40 if self.x <= 575
return true if self.x >= 575
end
end
#--------------------------------------------------------
# Scene_File modifié
# Scene et actions pour les sauvegardes
#--------------------------------------------------------
class Scene_File
def initialize(help_text)
@help_text = help_text
end
def main
# Initialisation des objets pour les différentes fenêtres
@help_window = Window_Help.new
@help_window.set_text(@help_text, 1)
@file_status_window = Window_FileStatus.new
@file_info_window = Window_FileInfo.new
@confirm_window = Window_FileConfirm.new
@confirm = false
@delete = false
@auto_retirer = false
# Affichage du fond
@sprite = Sprite.new
@sprite.bitmap = Cache.picture(AM_SAVE::FOND)
@help_window.opacity = 0
@savefile_windows = []
for i in 0..3
@savefile_windows.push(Window_SaveFile.new(i, make_filename(i)))
end
@file_index = 0
@savefile_windows[@file_index].selected = true
# Mise à jour comme toujours
Graphics.transition
loop do
Graphics.update
Input.update
update
if $scene != self
break
end
end
Graphics.freeze
@help_window.dispose
@file_status_window.dispose
@file_info_window.dispose
@confirm_window.dispose
@sprite.dispose
for i in @savefile_windows
i.dispose
end
end
def update
# Mise à jour des fenêtres
@help_window.update
@file_status_window.update
@file_info_window.update
@confirm_window.update
@sprite.update
for i in @savefile_windows
i.update
end
# Si la fenêtre de confirmation est active, on affiche la sélection
if @confirm_window.active
update_confirm
end
# On bouge la fenêtre d'info
@file_info_window.bouger
# Si on demande confirmation
if @confirm
# On bouge la fenêtre de confirmation après avoir retirer la fenêtre de Statut
if @file_status_window.retirer
@confirm_window.bouger
@confirm_window.active = true
save_reussie if @confirm_window.type == 3 if @confirm_window.bouger
end
else
# Réciproquement ...
if @confirm_window.retirer
@file_status_window.bouger
@confirm_window.active = false
end
end
# Si on demande le retirement automatique
if @auto_retirer
@auto_retirer = false
@savefile_windows[@file_index].refresh
# On affiche pendant 2 secondes
wait(2)
end
# Si on appuie sur Entrée
if Input.trigger?(Input::C)
# Si c'est pour une confirmation
if @confirm
case @confirm_window.index
# Annulation
when 2
Sound.play_cancel
@confirm = false
return
# validation
when 1
case @confirm_window.type
when 0
# on sauvegarde
on_decision(make_filename(@file_index))
save_reussie
when 1
# On supprime
delete(make_filename(@file_index))
@confirm_window.refresh(2)
@auto_retirer = true
end
end
else
# Si la scene est "Scene_Save"
if scene == 1
# Si il existe déjç une sauvegarde
if File.exist?(make_filename(@file_index))
@confirm_window.refresh
# On demande confirmation
@confirm = true
else
# Sinon, on sauvegarde directement
on_decision(make_filename(@file_index))
@confirm_window.refresh(3)
@confirm = true
end
else
# Si la scene est "Scene_Load"
on_decision(make_filename(@file_index))
end
end
return
end
# Si on appuie sur "Echap" : Annulation
if Input.trigger?(Input::B)
# On revient au menu
if !@confirm
on_cancel
else
# On enlève la fenêtr de confirmation
Sound.play_cancel
@confirm = false
end
return
end
# Si on appuie sur "Z"
if Input.trigger?(Input::SHIFT) and File.exist?(make_filename(@file_index))
# on demande confirmation
@confirm_window.refresh(1)
@confirm = true
return
end
# Si on choisit les slots
if !@confirm
if Input.repeat?(Input::DOWN)
if Input.trigger?(Input::DOWN) or @file_index < 3
@file_status_window.x = 640
@file_info_window.x = 640
Sound.play_cursor
@savefile_windows[@file_index].selected = false
@file_index = (@file_index + 1) % 4
@savefile_windows[@file_index].selected = true
# On réfraichit les fenêtres
@file_status_window.refresh(@file_index)
@file_info_window.refresh(@file_index)
return
end
end
if Input.repeat?(Input::UP)
if Input.trigger?(Input::UP) or @file_index > 0
@file_status_window.x = 640
@file_info_window.x = 640
Sound.play_cursor
@savefile_windows[@file_index].selected = false
@file_index = (@file_index + 3) % 4
@savefile_windows[@file_index].selected = true
# On réfraichit les fenêtres
@file_status_window.refresh(@file_index)
@file_info_window.refresh(@file_index)
return
end
end
end
end
# Le nom du fichier
def make_filename(file_index)
game = Files::Donnees.new(file_index)
return game.filename
end
# Sélection dans la fenêtre de confirmation
def update_confirm
if (Input.trigger?(Input::LEFT) or Input.trigger?(Input::UP)) and @confirm_window.index != 1
Sound.play_cursor
@confirm_window.index = 1
return
elsif (Input.trigger?(Input::RIGHT) or Input.trigger?(Input::DOWN)) and @confirm_window.index != 2
Sound.play_cursor
@confirm_window.index = 2
return
end
end
# Attente (Calcul en secondes)
def wait(time)
total_sec_dep = Graphics.frame_count / Graphics.frame_rate
loop do
total_sec = Graphics.frame_count / Graphics.frame_rate
Graphics.update
Input.update
if total_sec >= (total_sec_dep + time)
@confirm = false
break
end
end
return
end
# Si la sauvegarde est réussie, on éfraichit les fenêtres et on retire automatiquement
def save_reussie
@savefile_windows[@file_index].refresh
@file_status_window.refresh(@file_index)
@file_info_window.refresh(@file_index)
@confirm_window.refresh(4)
@auto_retirer = true
end
# Suppression du fichier
def delete(filename)
File.delete(filename)
@file_info_window.x = 640
end
end
#------------------------------------------------------------------------------
# Scene_Save
#------------------------------------------------------------------------------
class Scene_Save < Scene_File
def initialize
super("Voulez vous sauvegarder la partie ?")
end
def scene
return 1
end
def on_decision(filename)
Sound.play_save
file = File.open(filename, "wb")
write_save_data(file)
file.close
end
def on_cancel
Sound.play_cancel
$scene = Scene_Menu.new(4)
end
def write_save_data(file)
characters = []
for actor in $game_party.members
characters.push([actor.character_name, actor.character_index])
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
end
#------------------------------------------------------------------------------
# ¦ Scene_Load
#------------------------------------------------------------------------------
class Scene_Load < Scene_File
def scene
return 0
end
def initialize
$game_temp = Game_Temp.new
$game_temp.last_file_index = 0
latest_time = Time.at(0)
for i in 0..3
filename = make_filename(i)
if FileTest.exist?(filename)
file = File.open(filename, "r")
if file.mtime > latest_time
latest_time = file.mtime
$game_temp.last_file_index = i
end
file.close
end
end
super("Charger quelle partie?")
end
def on_decision(filename)
unless FileTest.exist?(filename)
Sound.play_buzzer
return
end
Sound.play_load
file = File.open(filename, "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
def on_cancel
Sound.play_cancel
$scene = Scene_Title.new
end
def read_save_data(file)
characters = Marshal.load(file)
Graphics.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)
if $game_system.version_id != $data_system.version_id
$game_map.setup($game_map.map_id)
$game_player.center($game_player.x, $game_player.y)
end
end
end