#==============================================================================
# ■ 快速存读档 by 老鹰（http://oneeyedeagle.lofter.com/）
#==============================================================================
$imported ||= {}
$imported["EAGLE-FastSL"] = true
#==============================================================================
# - 2021.6.6.16 修复list为空时，读档报错的问题
#==============================================================================
# - 本插件提供了一套基础的按键存读档接口，并且已经绑定在地图的刷新中
#------------------------------------------------------------------------------
# - 在地图上（包括事件执行时），按下对应按键可以快速存档/读档指定档位
#------------------------------------------------------------------------------
# - 注意：
#
#  ·由于默认Game_Interpreter事件解释器中，选择框利用了无法被序列化的Proc类，
#     因此当选项出现时，使用存档功能会出现存储失败的情况；
#     但如果用了其他选择框实现（譬如 AddOn-选择框扩展 by老鹰）覆盖默认Proc方式，
#     则可在选择框开启时进行存档
#
# - 本插件特别为事件中途的存读档进行了优化：
#     在默认机制中，存储的是下一条指令位置，
#       这导致若在选择框开启时进行存储，读档后解释器会将选择指令跳过
#     在本插件中，存储的是当前指令位置，
#       同时在读取时清除 $game_message 内容，确保重新执行当前指令
#
# - 本插件特别为选择框开启时的存读档进行了优化：
#     在默认机制中，读档后会直接进行选项，而不再显示存档前的对话框
#     在本插件中，若读档后为选择框，则将溯回至其相邻的上一个对话框，并重新显示
#
#------------------------------------------------------------------------------
# - 高级：
#
#  ·在需要允许进行快速存读档的场景中，新增 FastSL.update 即可增加该绑定，
#     但请注意，所存储的内容依旧为 DataManager 中的设置内容，默认不保存其他场景信息
#
#  ·在 save_success 方法处理存储成功后的操作，其中可以增加其它的提示内容
#    （譬如已经新增了利用 AddOn-并行对话 by老鹰 生成的对话框文本提示）
#==============================================================================

module FastSL
  #--------------------------------------------------------------------------
  # ● 【常量】控制是否允许快速存读档的开关ID
  #--------------------------------------------------------------------------
  S_ID_SL = 0
  #--------------------------------------------------------------------------
  # ● 【常量】控制快速存储档位序号的变量ID
  #--------------------------------------------------------------------------
  V_ID_FILE_INDEX = 9
  #--------------------------------------------------------------------------
  # ● 快速存档的按键判定成功？
  #--------------------------------------------------------------------------
  def self.save?
    Input.trigger?(:L)
  end
  #--------------------------------------------------------------------------
  # ● 快速读档的按键判定成功？
  #--------------------------------------------------------------------------
  def self.load?
    Input.trigger?(:R)
  end
  #--------------------------------------------------------------------------
  # ● 更新
  #--------------------------------------------------------------------------
  def self.update
    return if $game_switches[S_ID_SL] && $game_switches[S_ID_SL] == false
    return FastSL.save if FastSL.save?
    return FastSL.load if FastSL.load?
  end
  #--------------------------------------------------------------------------
  # ● 执行快速存档
  #--------------------------------------------------------------------------
  def self.save
    index = $game_variables[V_ID_FILE_INDEX]
    return save_success if DataManager.save_game(index)
    Sound.play_buzzer
  end
  #--------------------------------------------------------------------------
  # ● 执行快速存档成功
  #--------------------------------------------------------------------------
  def self.save_success
    if $imported["EAGLE-MessagePara"]
      t = "<msg>\\win[do-8o5dx0dy200w0h0fw1fh1z500]\\ins快速存储成功！</msg>"
      MESSAGE_PARA.add(:fast_save, t)
    end
    Sound.play_save
  end
  #--------------------------------------------------------------------------
  # ● 执行快速读档
  #--------------------------------------------------------------------------
  def self.load
    index = $game_variables[V_ID_FILE_INDEX]
    return load_success if DataManager.load_game(index)
    Sound.play_buzzer
  end
  #--------------------------------------------------------------------------
  # ● 快速读档成功
  #--------------------------------------------------------------------------
  def self.load_success
    Sound.play_load
    fadeout_all
    $game_system.on_after_load
    SceneManager.goto(Scene_Map)
  end
  #--------------------------------------------------------------------------
  # ● 淡出各种音效以及图像
  #--------------------------------------------------------------------------
  def self.fadeout_all(time = 1000)
    RPG::BGM.fade(time)
    RPG::BGS.fade(time)
    RPG::ME.fade(time)
    Graphics.fadeout(time * Graphics.frame_rate / 1000)
    RPG::BGM.stop
    RPG::BGS.stop
    RPG::ME.stop
  end
end
#=============================================================================
# ○ Game_Map
#=============================================================================
class Game_Map
  #--------------------------------------------------------------------------
  # ● 更新画面
  #     main : 事件解释器更新的标志
  #--------------------------------------------------------------------------
  alias eagle_fast_sl_update update
  def update(main = false)
    eagle_fast_sl_update(main)
    FastSL.update
  end
end
#===============================================================================
# ○ Game_System
#===============================================================================
class Game_System
  #--------------------------------------------------------------------------
  # ● 读档后的处理
  #--------------------------------------------------------------------------
  alias eagle_fast_sl_on_after_load on_after_load
  def on_after_load
    $game_message.clear # 因为已经去除了 @index+1，所以也需要清除对话框存储的信息
    eagle_fast_sl_on_after_load
  end
end
#=============================================================================
# ○ Game_Interpreter
#=============================================================================
class Game_Interpreter
  #--------------------------------------------------------------------------
  # ●（覆盖）储存实例
  #  去除了 @index+1，确保在当前事件指令位置反复存读时，@index不会递增
  #--------------------------------------------------------------------------
  def marshal_dump
    [@depth, @map_id, @event_id, @list, @index, @branch]
  end
  #--------------------------------------------------------------------------
  # ● （覆盖）读取实例
  #     obj : marshal_dump 中储存的实例（数组）
  #    恢复多个数据（@depth、@map_id 等）的状态，必要时重新创建纤程。
  #--------------------------------------------------------------------------
  def marshal_load(obj)
    @depth, @map_id, @event_id, @list, @index, @branch = obj
    after_marshal_load
    create_fiber
  end
  #--------------------------------------------------------------------------
  # ● 读取实例后的处理
  #--------------------------------------------------------------------------
  def after_marshal_load
    return if @list.nil?
    return if @list[@index] == nil
    # 特殊的，如果当前是选择框，检查上一个指令是否为对话
    if @list[@index].code == 102 && @index - 1 > 0
      while true
        @index = @index - 1 if @list[@index-1].code == 401 # 文字数据
        break if @list[@index-1].code == 101 # 找到对话框的头部信息
      end
      @index = @index - 1
    end
  end
end
