Mundo Maker
¡Bienvenid@ a Mundo Maker!

¿Quieres aprender todo sobre el RPG Maker?



Regístrate y forma parte de Mundo Maker.

[XP] Wecoc's Script SaveFiles Updater v1.0

Ver el tema anterior Ver el tema siguiente Ir abajo

RPG Maker XP [XP] Wecoc's Script SaveFiles Updater v1.0

Mensaje por Wecoc el 2016-02-07, 04:25

Éste script sirve para solucionar el siguiente problema:

Vuestro juego a medio hacer empieza a ser largo y tenéis partidas guardadas en varios puntos del juego, para testear.
En un momento dado decidís añadir un script que influye en la estructura de las clases por defecto. En general, el problema ahí es que al empezar una nueva partida todo funciona a la perfección, pero al cargar una de esas partidas sale un error muchas veces irreparable, debido a que fueron guardadas antes de incorporar los cambios efectuados por el script.

En ese caso solo puedes borrar las partidas hasta entonces guardadas y volver a testear de nuevo, o bien renunciar al nuevo script...

Pues el pluggin que he hecho intenta arreglar eso, creando una nueva partida y copiando todo lo de la vieja que aún sirve para así lograr una partida funcional.
Es de usar y tirar (no hace falta que os lo quedéis en el proyecto una vez fijadas las partidas) por lo que no pido créditos.

Código:
#==============================================================================
# [XP] Wecoc's Script SaveFiles Updater v1.0
#==============================================================================

#==============================================================================
# ** Módulo principal del script
#==============================================================================

module WEC_SSU
  
  ACTIVE = true           # Activa el script
  
  FULL_FOLDER = false     # Muestra el nombre entero de la carpeta actual
  
  SAVE_COPY = true        # Guarda una copia del archivo actualizado
  
  SHOW_COPY = true        # Muestra los archivos de copia en la carpeta
  
end

#==============================================================================
# ** Scene_Title
#==============================================================================

class Scene_Title
  #--------------------------------------------------------------------------
  # * Command: Continue
  #--------------------------------------------------------------------------
  alias wecssu_continue command_continue unless $@
  def command_continue
    # Cargar la nueva escena si el script está activado
    if WEC_SSU::ACTIVE == true
      $game_system.se_play($data_system.decision_se)
      $scene = Scene_Updater.new
    else
      wecssu_continue
    end
  end
end

#==============================================================================
# ** Dir
#==============================================================================

class Dir
  #--------------------------------------------------------------------------
  # * Dir.folders
  #--------------------------------------------------------------------------
  # Obtiene las carpetas contenidas en una carpeta
  #--------------------------------------------------------------------------
  def self.folders(folder)
    all_files = Dir.open(folder).entries
    all_files.delete(".") ; all_files.delete("..")
    result_files = []
    for file in all_files
      if FileTest.exist?(folder + "/" + file)
        ftype = File.ftype(folder + "/" + file) rescue nil
        result_files.push(file) if ftype == "directory"
      end
    end
    return result_files
  end
  #--------------------------------------------------------------------------
  # * Dir.files
  #--------------------------------------------------------------------------
  # Obtiene los archivos contenidos en una carpeta
  #   ext = extensión del archivo
  #--------------------------------------------------------------------------
  def self.files(folder, ext=nil)
    all_files = Dir.open(folder).entries
    result_files = []
    for file in all_files
      if FileTest.exist?(folder + "/" + file)
        ftype = File.ftype(folder + "/" + file) rescue nil
        result_files.push(file) if ftype == "file"
      end
    end
    return result_files if ext == nil
    return result_files.select {|d| d.include?("." + ext)}
  end
end

class String
  #--------------------------------------------------------------------------
  # * Inside Folders
  #--------------------------------------------------------------------------
  # Divide el nombre completo de una carpeta en una array
  # ordenada de todas sus carpetas ancestrales
  #--------------------------------------------------------------------------
  def inside_folders
    result = [""]
    n = 0
    return [self] if !self.include?("/")
    for i in 0...self.size
      if self[i].chr == "/"
        n += 1
        result[n] = ""
        next
      end
      result[n].concat(self[i].chr)
    end
    return result
  end
  #--------------------------------------------------------------------------
  # * File Ext
  #--------------------------------------------------------------------------
  # Obtiene la extensión de un archivo
  #--------------------------------------------------------------------------
  def file_ext
    r = self.rindex(".")
    return self[r..self.size]
  end
end

#==============================================================================
# ** Window_Files
#==============================================================================

class Window_Files < Window_Selectable
  
  # Extensiones de los archivos de guardado
  FILE_EXTENSIONS = ["rxdata"]
  
  # Carpeta actual
  attr_reader :folder
  
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize(x, y, width, height)
    super(x, y, width, height)
    @folder = Dir.getwd
    refresh
  end
  #--------------------------------------------------------------------------
  # * Get Item
  #--------------------------------------------------------------------------
  def item
    return @data[self.index]
  end
  #--------------------------------------------------------------------------
  # * Set current folder
  #--------------------------------------------------------------------------
  def folder=(folder)
    if folder == nil
      folder = Dir.getwd
    end
    if @folder != folder
      @folder = folder
      refresh
    end
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    if self.contents != nil
      self.contents.dispose
      self.contents = nil
    end
    @data = []
    # Set current folders
    folders = Dir.folders(@folder)
    # Set current files
    files = []
    for ext in FILE_EXTENSIONS
      files.concat Dir.files(@folder, ext)
    end
    # Add folders
    for i in 0...folders.size
      @data.push(folders[i])
    end
    # Add files
    for i in 0...files.size
      # Ignora los archivos _copy generados por seguridad
      next if files[i].include?("_copy")
      @data.push(files[i])
    end
    # Add "copy" files
    if WEC_SSU::SHOW_COPY == true
      for i in 0...files.size
        # Muestra los archivos _copy al final
        next if !files[i].include?("_copy")
        @data.push(files[i])
      end
    end
    # If item count is not 0, make a bit map and draw all items
    @item_max = @data.size
    if @item_max > 0
      self.contents = Bitmap.new(width - 32, row_max * 32)
      for i in 0...@item_max
        draw_item(i)
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Draw Item
  #     index : item number
  #--------------------------------------------------------------------------
  def draw_item(index)
    item = @data[index]
    if folder?(index)
      self.contents.font.color = normal_color
    else
      self.contents.font.color = system_color
    end
    x = 4
    y = index * 32
    self.contents.draw_text(x, y, 640 - 32, 32, item, 0)
  end
  
  def folder?(index)
    return !file?(index)
  end
  
  def file?(index)
    item = @data[index]
    for ext in FILE_EXTENSIONS
      if item.include?(ext)
        return true
      end
    end
    return false
  end
end

#==============================================================================
# ** Scene_Updater
#==============================================================================

class Scene_Updater
  #--------------------------------------------------------------------------
  # * Main Processing
  #--------------------------------------------------------------------------
  def main
    # Crea la help window
    @help_window = Window_Help.new
    @help_window.set_text("¿Qué archivo quieres actualizar?")
    # Define la carpeta del proyecto como principal
    @folder = Dir.getwd
    # Crea la folder window (muestra la carpeta actual)
    @folder_window = Window_Help.new
    @folder_window.y = 64
    @folder_window.set_text(folder_name)
    # Crea la files window (muestra los archivos dentro de la carpeta)
    @files_window = Window_Files.new(0, 128, 640, 480 - 128)
    @files_window.index = 0
    @files_window.active = true
    # Execute transition
    Graphics.transition
    # Main loop
    loop do
      # Update game screen
      Graphics.update
      # Update input information
      Input.update
      # Frame update
      update
      # Abort loop if screen is changed
      if $scene != self
        break
      end
    end
    # Prepare for transition
    Graphics.freeze
    # Dispose of windows
    @help_window.dispose
    @folder_window.dispose
    @files_window.dispose
  end
  #--------------------------------------------------------------------------
  # * Folder Name
  #--------------------------------------------------------------------------
  def folder_name
    if WEC_SSU::FULL_FOLDER == true
      return @folder.to_s
    else
      f = @folder.inside_folders
      wd_f = Dir.getwd.inside_folders
      f.delete("")
      folders = f[0] + "/.../"
      folders += wd_f[wd_f.size - 1] + "/"
      f -= wd_f
      for i in 0...f.size
        folders += f[i] + "/"
      end
      return folders
    end
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    @folder_window.update
    @files_window.update
    # Update current folder
    if @folder != @files_window.folder
      @folder = @files_window.folder
      @folder_window.set_text(folder_name)
    end
    # If B button was pressed
    if Input.trigger?(Input::B)
      $game_system.se_play($data_system.cancel_se)
      # Si la carpeta actual es la del proyecto, vuelve a la escena de Título
      if @folder == Dir.getwd
        $scene = Scene_Title.new
        return
      end
      # Tira a la carpeta anterior a la actual
      folders = @folder.inside_folders
      last_folder = folders[folders.size-1]
      new_folder = folders[0...folders.size-1]
      new_folder.delete("")
      new_folder = new_folder.join("/")
      @files_window.folder = new_folder
      @files_window.index = Dir.folders(new_folder).index(last_folder)
      return
    end
    # If C button was pressed
    if Input.trigger?(Input::C)
      # Si el item actual es una carpeta
      if @files_window.folder?(@files_window.index)
        $game_system.se_play($data_system.decision_se)
        # Abre la carpeta seleccionada
        new_folder = @folder + "/" + @files_window.item
        @files_window.folder = new_folder
        @files_window.index = 0
        return
      # Si el item actual es un archivo
      else
        filename = @folder + "/" + @files_window.item
        # Actualiza el archivo
        restore_file(filename)
      end
    end
  end
  
  def restore_file(filename)
    # Carga el archivo actual
    begin
      file = File.open(filename, "rb")
        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)
      file.close
    rescue
      # Archivo no válido
      p "Invalid file! - This is not a Save File"
      return
    end
    # Crea una copia del archivo
    if WEC_SSU::SAVE_COPY == true
      file_ext = filename.file_ext
      filename_copy = filename[0...filename.size - file_ext.size]
      filename_copy = filename_copy + "_copy" + file_ext
      file = File.open(filename_copy, "wb")
        characters = []
        for i in 0...game_party.actors.size
          actor = game_party.actors[i]
          characters.push([actor.character_name, actor.character_hue])
        end
        Marshal.dump(characters, file)
        Marshal.dump(Graphics.frame_count, file)
        Marshal.dump(game_system, file)
        Marshal.dump(game_switches, file)
        Marshal.dump(game_variables, file)
        Marshal.dump(game_self_switches, file)
        Marshal.dump(game_screen, 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)
      file.close
    end
    # Crea una nueva partida
    $game_temp          = Game_Temp.new
    $game_system        = Game_System.new
    $game_switches      = Game_Switches.new
    $game_variables     = Game_Variables.new
    $game_self_switches = Game_SelfSwitches.new
    $game_screen        = Game_Screen.new
    $game_actors        = Game_Actors.new
    $game_party         = Game_Party.new
    $game_troop         = Game_Troop.new
    $game_map           = Game_Map.new
    $game_player        = Game_Player.new
    $game_party.setup_starting_members
    $game_map.setup($data_system.start_map_id)
    $game_player.moveto($data_system.start_x, $data_system.start_y)
    $game_player.refresh
    $game_map.autoplay
    $game_map.update
    
    # Define los datos de la partida cargada a la nueva partida
    data_names = ["system", "switches", "variables", "self_switches",
                  "screen", "actors", "party", "troop", "map", "player"]
    for data in data_names
      new_variables = eval("$game_#{data}.instance_variables")
      variables     = eval("game_#{data}.instance_variables")
      for i in new_variables
        if variables.include?(i)
          s = eval("game_#{data}.instance_variable_get(i)")
          e = eval("$game_#{data}.instance_variable_get(i)")
          if e != s
            eval("$game_#{data}.instance_variable_set(i, s)")
          end
        end
      end
    end
    # Reescribe la partida cargada por la nueva partida
    file = File.open(filename, "wb")
      characters = []
      for i in 0...$game_party.actors.size
        actor = $game_party.actors[i]
        characters.push([actor.character_name, actor.character_hue])
      end
      Marshal.dump(characters, file)
      Marshal.dump(Graphics.frame_count, file)
      Marshal.dump($game_system, file)
      Marshal.dump($game_switches, file)
      Marshal.dump($game_variables, file)
      Marshal.dump($game_self_switches, file)
      Marshal.dump($game_screen, 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)
    file.close
    # Refresca la ventana
    @files_window.refresh
    $game_system.se_play($data_system.save_se)
  end
end

Instrucciones básicas

Copiad el script encima de main. Empezad el juego desde el Editor e id a Cargar.
Os saldrá una ventana con las carpetas del juego y con los archivos de guardado. Normalmente salen en la carpeta general del juego, pero si los tenéis en una carpeta de Archivo podéis navegar por las carpetas usando Aceptar (C) y Cancelar (X).



Pulsad Aceptar encima del archivo de guardado que queráis actualizar. Simplemente sonará el ruido que hace de "Guardar". Luego cerrad el juego.
Id al script y buscad la primera línea donde dice ACTIVE = true y le ponéis false, desactivando totalmente el script.
Luego volvéis a probar el proyecto e intentáis cargar la partida. Si todo funciona bien ahora debería cargarse bien el juego. ¡Ya tenéis la partida actualizada!

Si no funcionara bien tranquilos porque el script hace una copia del archivo original antes de intentar actualizarlo. Lo guarda en la misma carpeta con el mismo nombre + _copy

Una vez hechos los cambios podéis borrar el script y continuar con vuestra vida makera ;D

Instrucciones avanzadas

El módulo WEC_SSU tiene éstas globales:
ACTIVE controla si el script está funcionando o no.
FULL_FOLDER cambia el modo en el que se muestra el nombre de la carpeta en la ventana de ayuda. Si véis en la imagen anterior como el nombre era muy largo salió con "..." para abreviar. Si en cambio activáis ésta variable se verá entero.
SAVE_COPY controla si se guarda o no el archivo "_copy" de seguridad. Lo recomiendo mucho porque como dije, es un script funcional y puede haber casos en los que el cambio del otro script sea tan severo que no sirva el pluggin.
SHOW_COPY define si se muestran en la carpeta los archivos "_copy"

Es posible que con una série de cambios simples se pueda ampliar la compatibilidad del script a VX y Ace, y de hecho algunas partes ya las planteé de modo que no sea tan complicado. Como yo uso el RPG maker XP y no tengo los demás no haré esa ampliación pero si alguien quiere atreverse le animo a intentarlo :D


Lo he probado con Wecoc's Message System 1.0, RAMP Engine, Script de andar con cambio de pie y algún otro y funciona.

En cambio en los que modifican el modo en el que se cargan y guardan los archivos (órden del Marshal o añadir nuevas globales ahí como $game_maps) no se puede arreglar, de hecho en algunos ni siquiera lee el archivo antíguo como archivo de guardado.

Finalmente también hay algún caso extraño en el que falla por razones desconocidas, como en el caso de Sistema de Dia y Noche.

En resumen, no os garantizo que funcione pero en algunos casos os puede ahorrar mucho tiempo.
avatar
Wecoc
Administrador
Administrador



Créditos 12286

Gracias : 646

Volver arriba Ir abajo

Ver el tema anterior Ver el tema siguiente Volver arriba


Permisos de este foro:
No puedes responder a temas en este foro.