#encoding:utf-8
# Sion 鼠标系统(SionMouseSystem)v3.02  (2014/2/20)
# ·需· Sion_MouseBase v3.00+
 
# v3.03(2014/6/9)  优化事件中的地图卷动命令、等待命令之间的衔接
# v3.02(2014/2/20) 事件执行过程中,卷动地图后不会自动跳转到玩家位置了
 
 
=begin 说明  
 
  主要功能
 
    1,自动寻路,按住 D 键可以扩大寻路的范围
    2,变量输入框改良
    3,鼠标启动事件:
      在事件中加入“注释”:鼠标启动
      该事件将无法用其它方式启动,只能用鼠标左键点击启动
      
    3.00 新增鼠标滚轮支持,菜单可以直接用鼠标滚轮翻页了
         现在在光标矩形外按鼠标不会响应了,必须移动到对应的选项上按才行。
         还改进了一些个蛋挞的问题。
         
      
  鼠标指针图片 MouseCursor.png 放入 Graphics\System 文件夹
  路径点指示图片 $Arrow.png 放入 Graphics\Characters 文件夹
  如果未放入会使用RM自带图片代替缺失文件
 
=end
 
 
 
#==============================================================================
# ■ 常数设置 
#==============================================================================
module KsOfSion
  Clip_Cursor    = false    # 鼠标锁定在游戏窗口内,需要关闭设置为false
  Dbclick_Frame  = 15      # 双击的最大间隔帧数。在地图画面双击进行奔跑
  New_Scroll     = true    # 更改地图卷动方式,需要关闭设置为false
  Map_Scroll_Spd = 1.0     # 卷动速度
  Menu_Set_Pos   = false   # 打开菜单时将鼠标移动到光标处
  Break_Steps    = 30      # 鼠标寻路最大步数,防止路径太长导致卡帧
#                             “30” 是默认显示格子数 长(17) + 宽(13)
  Find_Path_Key  = 0x44    # 扩大寻路范围至全地图按键 0x44 对应 D键
                           # 查阅 NovaBase 中的键盘表修改,设为 0 禁用此功能
end
 
#
class Move_Sign < Game_Character # ■ 用来显示路径点的类
attr_accessor :direction
  def init_public_members
    @character_name  = '!$Arrow'# 路径点箭头,置于.\Graphics\Characters文件夹
    @character_index = 0        # 图片索引。$开头的行走图设为0
    @move_speed      = 5        # 踏步速度
    @step_anime      = true     # 踏步动画(如果想使用静态图标就关闭这个)
    @opacity         = 255      # 不透明度
    @blend_type      = 0        # 图片合成方式,默认为0(正常)
    @direction       = 2        # 朝向,2 4 6 8 分别对应行走图第1 2 3 4 列
    @priority_type   = 1        # 优先级(默认与人物同级:1)
    # 如果 $Arrow.png 不在对应的文件夹内,弹出提示,并使用游戏一张内置的行走图
 
#============================= 参数设置完毕 ===================================
    unless File.exist?('Graphics/Characters/' + @character_name + '.png')
      @character_name  = '!Flame'
      @character_index = 6
    end
    @direction_fix = false
    @move_frequency = 6
    @walk_anime = true
    @pattern = 1
    @through = true
    @bush_depth = 0
    @animation_id = 0
    @balloon_id = 0
    @transparent = true
    @id = 0
    @x = 0
    @y = 0
    @real_x = 0
    @real_y = 0
    @tile_id = 0
  end
end
#==============================================================================
# ■ SceneManager
#==============================================================================
class << SceneManager
alias_method :sion_mouse_run, :run
alias_method :sion_mouse_call, :call
alias_method :sion_mouse_return, :return
 
  def run
    Mouse.activate
    sion_mouse_run
  end
  def call(scene_class, *args)
    $game_map.prepare_reset_mouse_pos if @scene.instance_of?(Scene_Map)
    sion_mouse_call(scene_class, *args)
  end
  def return
    sion_mouse_return
    $game_map.reset_mouse_pos if KsOfSion::Menu_Set_Pos &&
      @scene.instance_of?(Scene_Map)
  end
end
class << Mouse
  attr_reader :sprite
end
class << Input
alias_method :sion_mouse_press?,   :press?
alias_method :sion_mouse_trigger?, :trigger?
alias_method :sion_mouse_repeat?,  :repeat?
alias_method :sion_mouse_update,   :update
 
  def update
    Mouse.update
    sion_mouse_update
  end
  def press?(key)
    return true if sion_mouse_press?(key)
    return Input.key_press?(0x01) if key == :C
    return Input.key_press?(0x02) if key == :B
    return false
  end
  def trigger?(key)
    return true if sion_mouse_trigger?(key)
    return Input.key_trigger?(0x01) if key == :C
    return Input.key_trigger?(0x02) if key == :B
    return false
  end
  def repeat?(key)
    return true if sion_mouse_repeat?(key)
    return Input.key_repeat?(0x01) if key == :C
    return Input.key_repeat?(0x02) if key == :B
    return false
  end
end
 
 
#==============================================================================
# ■ Window_Selectable
#------------------------------------------------------------------------------
#  拥有光标移动、滚动功能的窗口
#==============================================================================
class Window_Selectable
  #--------------------------------------------------------------------------
  # ● 初始化
  #--------------------------------------------------------------------------
  alias sion_mouse_initialize initialize
  def initialize(x, y, width, height)
    sion_mouse_initialize(x, y, width, height)
    @move_state = 0
  end
  #--------------------------------------------------------------------------
  # ● 更新
  #--------------------------------------------------------------------------
  alias sion_mouse_update update
  def update
    sion_mouse_update
    update_mouse_cursor
  end
  #--------------------------------------------------------------------------
  # ● 按下确定键的处理
  #--------------------------------------------------------------------------
  alias sion_mouse_process_ok process_ok
  def process_ok
    return if Input.key_trigger?(0x01) && mouse_out_rect?
    sion_mouse_process_ok
  end
  #--------------------------------------------------------------------------
  # ● 判断鼠标是位于光标矩形处
  #--------------------------------------------------------------------------
  def mouse_out_rect?
    if viewport.nil?
      vp_x, vp_y = 0, 0
    else
      vp_x = viewport.rect.x - viewport.ox
      vp_y = viewport.rect.y - viewport.oy
    end
    mouse_rx = ox + Mouse.x - (x + vp_x + standard_padding )
    mouse_ry = oy + Mouse.y - (y + vp_y + standard_padding )
    return cursor_rect.x > mouse_rx ||
           cursor_rect.y > mouse_ry ||
           cursor_rect.x + cursor_rect.width < mouse_rx ||
           cursor_rect.y + cursor_rect.height< mouse_ry
  end
  #--------------------------------------------------------------------------
  # ● 启动后设置鼠标到index位置 / 重置鼠标滚轮状态
  #--------------------------------------------------------------------------
  def activate
    @need_set_pos = true if KsOfSion::Menu_Set_Pos
    Mouse.reset_z
    super
  end
  #--------------------------------------------------------------------------
  # ● 更新鼠标和光标的位置
  #--------------------------------------------------------------------------
  def update_mouse_cursor
    if active
      if @need_set_pos
        @need_set_pos = false
        set_mouse_pos
      elsif cursor_movable?
        Input.dir4.zero? ? set_cursor : set_mouse_pos
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● 将光标设置到鼠标所在的位置,附带卷动菜单的功能
  #--------------------------------------------------------------------------
  def set_cursor
    mouse_row, mouse_col = mouse_window_area
    if    mouse_row == -1
      @move_state += 1 if need_scroll?
      cursor_up if (@move_state - 1) % 4 == 0 && !is_horzcommand?
    elsif mouse_row == -2
      @move_state += 1 if need_scroll?
      cursor_down if (@move_state - 1) % 4 == 0 && !is_horzcommand?
    elsif mouse_col == -1
      @move_state += 1 if need_scroll?
      cursor_left if (@move_state - 1) % 16 == 0 && is_horzcommand?
    elsif mouse_col == -2
      @move_state += 1 if need_scroll?
      cursor_right if (@move_state - 1) % 16 == 0 && is_horzcommand?
    else
      @move_state = 0
      new_index = (top_row + mouse_row) * col_max + mouse_col
      select(new_index) if new_index < item_max && new_index != @index
    end
    update_mouse_scroll
  end
  #--------------------------------------------------------------------------
  # ● 判断鼠标位于菜单的第几行、第几列
  #--------------------------------------------------------------------------
  def mouse_window_area
    if viewport.nil? # necessary!
      vp_x, vp_y = 0, 0
    else
      vp_x = viewport.rect.x - viewport.ox
      vp_y = viewport.rect.y - viewport.oy
    end
    mouse_x = Mouse.x
    mouse_y = Mouse.y
    item_x1 = vp_x + x + standard_padding 
    item_y1 = vp_y + y + standard_padding
    item_x2 = vp_x + x - standard_padding + width
    item_y2 = vp_y + y - standard_padding + height
    if mouse_x < item_x1
      mouse_col = -1
    elsif mouse_x > item_x2
      mouse_col = -2
    else
      mouse_col = col_max * (mouse_x - item_x1) / (item_x2 - item_x1)
    end
    if mouse_y < item_y1
      mouse_row = -1
    elsif mouse_y > item_y2
      mouse_row = -2
    else
      mouse_row = page_row_max * (mouse_y - item_y1 - 1) / (item_y2 - item_y1)
    end
    return mouse_row, mouse_col
  end
  #--------------------------------------------------------------------------
  # ● 更新鼠标滚轮
  #--------------------------------------------------------------------------
  def update_mouse_scroll
    z = Mouse.z
    return if z == 0
    if need_scroll?
      if z < 0
        cursor_pagedown
      else
        cursor_pageup
      end
    end
    Mouse.reset_z
  end
  #--------------------------------------------------------------------------
  # ● 方向键移动光标时将鼠标移动到对应的光标位置
  #--------------------------------------------------------------------------
  def set_mouse_pos
    if viewport.nil? # necessary!
      vp_x, vp_y = 0, 0
    else
      vp_x = viewport.rect.x - viewport.ox
      vp_y = viewport.rect.y - viewport.oy
    end
    item_x1 = vp_x + x + standard_padding 
    item_y1 = vp_y + y + standard_padding
    get_index = @index < 0 ? 0 : @index 
    row = get_index / col_max - top_row
    col = get_index % col_max
    new_x = item_x1 + item_width * (col + 0.5)
    new_y = item_y1 + item_height * (row + 0.5)
    Mouse.set_pos(new_x, new_y)
  end
  #--------------------------------------------------------------------------
  # ● 判断菜单是否需要卷动
  #--------------------------------------------------------------------------
  def need_scroll?
    item_max > col_max * page_row_max
  end
  #--------------------------------------------------------------------------
  # ● 判断是否为水平卷动菜单
  #--------------------------------------------------------------------------
  def is_horzcommand?
    return false
  end
end
 
class Window_HorzCommand
  #--------------------------------------------------------------------------
  # ● 判断是否为水平卷动菜单
  #--------------------------------------------------------------------------
  def is_horzcommand?
    return true
  end
end
 
#==============================================================================
# ■ Window_NameInput
#------------------------------------------------------------------------------
#  名字输入画面中,选择文字的窗口。
#==============================================================================
class Window_NameInput
  #--------------------------------------------------------------------------
  # ● 设置列数
  #--------------------------------------------------------------------------
  def col_max
    return 10
  end
  #--------------------------------------------------------------------------
  # ● 设置填充的Item个数
  #--------------------------------------------------------------------------
  def item_max
    return 90
  end
  #--------------------------------------------------------------------------
  # ● 设置填充的Item个数
  #--------------------------------------------------------------------------
  def item_width
    return 32
  end
  #--------------------------------------------------------------------------
  # ● 判断鼠标位于菜单的第几行、第几列
  #--------------------------------------------------------------------------
  def mouse_window_area
    if viewport.nil?
      vp_x, vp_y = 0, 0
    else
      vp_x = viewport.rect.x - viewport.ox
      vp_y = viewport.rect.y - viewport.oy
    end
    mouse_x = Mouse.x
    mouse_y = Mouse.y
    item_x1 = vp_x + x + standard_padding 
    item_y1 = vp_y + y + standard_padding
    item_x2 = vp_x + x - standard_padding + width
    item_y2 = vp_y + y - standard_padding + height
    if mouse_x < item_x1
      mouse_col = -1
    elsif mouse_x > item_x2
      mouse_col = -2
    elsif mouse_x < item_x1 + 160
      mouse_col = (mouse_x - item_x1)/32
    elsif mouse_x > item_x2 - 160
      mouse_col = 9 - (item_x2 - mouse_x)/32
    else
      mouse_col = mouse_x > x + width/2 ? 5 : 4
    end
    if mouse_y < item_y1
      mouse_row = -1
    elsif mouse_y > item_y2
      mouse_row = -2
    else
      mouse_row = page_row_max * (mouse_y - item_y1 - 1)/(item_y2 - item_y1)
    end
    return mouse_row, mouse_col
  end
  #--------------------------------------------------------------------------
  # ● 方向键移动光标时将鼠标移动到对应的光标位置
  #--------------------------------------------------------------------------
  def set_mouse_pos
    if viewport.nil? # necessary!
      vp_x, vp_y = 0, 0
    else
      vp_x = viewport.rect.x - viewport.ox
      vp_y = viewport.rect.y - viewport.oy
    end
    item_x1 = vp_x + x + standard_padding 
    item_y1 = vp_y + y + standard_padding
    get_index = @index < 0 ? 0 : @index 
    row = get_index / col_max - top_row
    col = get_index % col_max
    new_x = item_x1 + item_width * (col + 0.5)
    new_y = item_y1 + item_height * (row + 0.5)
    new_x += 14 if col > 4
    Mouse.set_pos(new_x, new_y)
  end
end
 
#==============================================================================
# ■ Window_NumberInput
#------------------------------------------------------------------------------
#  重写了数值输入的方法以适应鼠标
#==============================================================================
class Window_NumberInput < Window_Base
  #--------------------------------------------------------------------------
  # ● 定义实例变量
  #--------------------------------------------------------------------------
  attr_reader :extra_window
  #--------------------------------------------------------------------------
  # ● 初始化
  #--------------------------------------------------------------------------
  alias sion_mouse_initialize initialize
  def initialize(arg)
    sion_mouse_initialize(arg)
    create_extra_window
  end
  #--------------------------------------------------------------------------
  # ● 启动
  #--------------------------------------------------------------------------
  alias sion_mouse_start start
  def start
    sion_mouse_start
    deactivate
    extra_start
  end
  #--------------------------------------------------------------------------
  # ● 创建新的数值输入窗口
  #--------------------------------------------------------------------------
  def create_extra_window
    @extra_window = Window_NumberInput_Ex.new
    @extra_window.x = (Graphics.width - @extra_window.width) / 2
    @extra_window.number_proc  = Proc.new {|n| @number = n }
    @extra_window.index_proc   = Proc.new {|n| @index = n }
    @extra_window.close_proc   = Proc.new { close }
    @extra_window.refresh_proc = Proc.new { refresh }
  end
  #--------------------------------------------------------------------------
  # ● 激活新窗口
  #--------------------------------------------------------------------------
  def extra_start
    case $game_message.position
      when 0; @extra_window.y = y + height + 4
      when 1; @extra_window.y = @message_window.y - @extra_window.height - 8
      when 2; @extra_window.y = y - @extra_window.height - 4
      else  ; @extra_window.y = 8
    end
    @extra_window.variable_id = $game_message.num_input_variable_id
    @extra_window.digits_max  = @digits_max
    @extra_window.number      = @number
    @extra_window.open
    @extra_window.activate
  end
  #--------------------------------------------------------------------------
  # ● 更新
  #--------------------------------------------------------------------------
  def update
    super
    @extra_window.update
    update_cursor
  end
  #--------------------------------------------------------------------------
  # ● 关闭窗口
  #--------------------------------------------------------------------------
  def close
    super
    @extra_window.close
    @extra_window.deactivate
  end
end
 
#==============================================================================
# ■ Window_NumberInput_Ex
#------------------------------------------------------------------------------
#  新的数值输入窗口(NewClass)
#==============================================================================
class Window_NumberInput_Ex < Window_Selectable
  #--------------------------------------------------------------------------
  # ● 定义实例变量
  #--------------------------------------------------------------------------
  attr_accessor :number_proc
  attr_accessor :index_proc
  attr_accessor :close_proc
  attr_accessor :refresh_proc
  attr_accessor :number
  attr_accessor :digits_max
  attr_accessor :variable_id
  #--------------------------------------------------------------------------
  # ● 数字表
  #--------------------------------------------------------------------------
  TABLE = [  7,  8,  9,
             4,  5,  6,
             1,  2,  3,
            '←',0,'确定',]
  #--------------------------------------------------------------------------
  # ● 初始化对象
  #--------------------------------------------------------------------------
  def initialize
    super(0, 0, 120, fitting_height(4))
    self.openness = 0
    @index = 0
    @number = 0
    @old_window_index = 0
    @digits_max = 0
    12.times {|i| draw_text(item_rect(i), TABLE[i], 1) }
  end
  #--------------------------------------------------------------------------
  # ● 获取项目的绘制矩形
  #--------------------------------------------------------------------------
  def item_rect(index)
    rect = Rect.new
    rect.x = index % 3 * 32
    rect.y = index / 3 * line_height
    rect.width = 32
    rect.height = line_height
    return rect
  end
  #--------------------------------------------------------------------------
  # ● 将光标设置到鼠标所在的位置
  #--------------------------------------------------------------------------
  def set_cursor
    mouse_row, mouse_col = mouse_window_area
    if mouse_row >= 0 && mouse_col >= 0
      new_index = mouse_row * 3 + mouse_col
      select(new_index) if new_index <= 11
    end
  end
  #--------------------------------------------------------------------------
  # ● 判断鼠标位于新数值输入窗口的第几行、第几列
  #--------------------------------------------------------------------------
  def mouse_window_area
    if viewport.nil?
      vp_x, vp_y = 0, 0
    else
      vp_x = viewport.rect.x - viewport.ox
      vp_y = viewport.rect.y - viewport.oy
    end
    mouse_x = Mouse.x
    mouse_y = Mouse.y
    item_x1 = vp_x + x + standard_padding 
    item_y1 = vp_y + y + standard_padding
    item_x2 = vp_x + x - standard_padding + width
    item_y2 = vp_y + y - standard_padding + height
    if mouse_x < item_x1
      mouse_col = -1
    elsif mouse_x > item_x2
      mouse_col = -2
    else
      mouse_col = (mouse_x - item_x1) / 32
    end
    if mouse_y < item_y1
      mouse_row = -1
    elsif mouse_y > item_y2
      mouse_row = -2
    else
      mouse_row = 4 * (mouse_y - item_y1 - 1) / (item_y2 - item_y1)
    end
    return mouse_row, mouse_col
  end
  #--------------------------------------------------------------------------
  # ● 获取文字
  #--------------------------------------------------------------------------
  def get_number
    return false if @index == 9 || @index == 11
    return TABLE[@index]
  end
  #--------------------------------------------------------------------------
  # ● 判定光标位置是否在“退格”上
  #--------------------------------------------------------------------------
  def is_delete?
    @index == 9
  end
  #--------------------------------------------------------------------------
  # ● 判定光标位置是否在“确定”上
  #--------------------------------------------------------------------------
  def is_ok?
    @index == 11
  end
  #--------------------------------------------------------------------------
  # ● 更新光标
  #--------------------------------------------------------------------------
  def update_cursor
    cursor_rect.set(item_rect(@index))
  end
  #--------------------------------------------------------------------------
  # ● 判定光标是否可以移动
  #--------------------------------------------------------------------------
  def cursor_movable?
    active
  end
  #--------------------------------------------------------------------------
  # ● 光标向下移动
  #     wrap : 允许循环
  #--------------------------------------------------------------------------
  def cursor_down(wrap)
    if @index < 9 or wrap
      @index = (index + 3) % 12
    end
  end
  #--------------------------------------------------------------------------
  # ● 光标向上移动
  #     wrap : 允许循环
  #--------------------------------------------------------------------------
  def cursor_up(wrap)
    if @index >= 3 or wrap
      @index = (index + 9) % 12
    end
  end
  #--------------------------------------------------------------------------
  # ● 光标向右移动
  #     wrap : 允许循环
  #--------------------------------------------------------------------------
  def cursor_right(wrap)
    if @index % 3 < 2
      @index += 1
    elsif wrap
      @index -= 2
    end
  end
  #--------------------------------------------------------------------------
  # ● 光标向左移动
  #     wrap : 允许循环
  #--------------------------------------------------------------------------
  def cursor_left(wrap)
    if @index % 3 > 0
      @index -= 1
    elsif wrap
      @index += 2
    end
  end
  #--------------------------------------------------------------------------
  # ● 处理光标的移动
  #--------------------------------------------------------------------------
  def process_cursor_move
    super
    update_cursor
  end
  #--------------------------------------------------------------------------
  # ● “确定”、“删除字符”和“取消输入”的处理
  #--------------------------------------------------------------------------
  def process_handling
    return unless open? && active
    process_jump if Input.trigger?(:A)
    process_back if Input.repeat?(:B)
    process_ok   if Input.trigger?(:C)
  end
  #--------------------------------------------------------------------------
  # ● 跳转“确定”
  #--------------------------------------------------------------------------
  def process_jump
    if @index != 11
      @index = 11
      Sound.play_cursor
    end
  end
  #--------------------------------------------------------------------------
  # ● 后退一个字符
  #--------------------------------------------------------------------------
  def process_back
    Sound.play_cancel
    place = 10 ** (@digits_max - 1 - @old_window_index)
    n = (@number / place) % 10
    @number -= n * place
    @number_proc.call(@number)
    @old_window_index -= 1 if @old_window_index > 0
    @index_proc.call(@old_window_index)
    @refresh_proc.call
  end
  #--------------------------------------------------------------------------
  # ● 按下确定键时的处理
  #--------------------------------------------------------------------------
  def process_ok
    return if Input.key_trigger?(0x01) && mouse_out_rect?
    if get_number
      Sound.play_cursor
      place = 10 ** (@digits_max - 1 - @old_window_index)
      n = get_number - (@number / place) % 10
      @number += n * place
      @number_proc.call(@number)
      @old_window_index += 1 if @old_window_index < @digits_max - 1
      @index_proc.call(@old_window_index)
      @refresh_proc.call
    elsif is_delete?
      process_back
    elsif is_ok?
      on_input_ok
    end
  end
  #--------------------------------------------------------------------------
  # ● 确定
  #--------------------------------------------------------------------------
  def on_input_ok
    @index = 0
    @old_window_index = 0
    $game_variables[@variable_id] = @number
    Sound.play_ok
    @close_proc.call
  end
  #--------------------------------------------------------------------------
  # ● 方向键移动光标时将鼠标移动到对应的光标位置
  #--------------------------------------------------------------------------
  def set_mouse_pos
    if viewport.nil? # necessary!
      vp_x, vp_y = 0, 0
    else
      vp_x = viewport.rect.x - viewport.ox
      vp_y = viewport.rect.y - viewport.oy
    end
    item_x1 = vp_x + x + standard_padding 
    item_y1 = vp_y + y + standard_padding
    get_index = @index < 0 ? 0 : @index 
    new_x = item_x1 + 32 * (get_index % 3 + 0.5)
    new_y = item_y1 + 24 * (get_index / 3 + 0.5)
    Mouse.set_pos(new_x, new_y)
  end
end
 
#==============================================================================
# ■ Window_Message
#------------------------------------------------------------------------------
#  显示文字信息的窗口。
#==============================================================================
class Window_Message < Window_Base
  #--------------------------------------------------------------------------
  # ● 处理数值的输入(覆盖原方法)
  #--------------------------------------------------------------------------
  def input_number
    @number_window.start
    Fiber.yield while @number_window.extra_window.active
  end
end
 
#==============================================================================
# ■ Window_PartyCommand
#------------------------------------------------------------------------------
#  战斗画面中,选择“战斗/撤退”的窗口。
#==============================================================================
class Window_PartyCommand < Window_Command
  #--------------------------------------------------------------------------
  # ● 方向键移动光标时将鼠标移动到对应的光标位置
  #--------------------------------------------------------------------------
  def set_mouse_pos
    if viewport.nil?
      vp_x, vp_y = 0, 0
    else
      #vp_x = viewport.rect.x - viewport.ox
      vp_y = viewport.rect.y - viewport.oy
    end
    item_x1 = x + standard_padding 
    item_y1 = vp_y + y + standard_padding
    get_index = @index < 0 ? 0 : @index 
    row = get_index / col_max - top_row
    col = get_index % col_max
    new_x = item_x1 + item_width * (col + 0.5)
    new_y = item_y1 + item_height * (row + 0.5)
    Mouse.set_pos(new_x, new_y)
  end
end
 
#==============================================================================
# ■ Window_ActorCommand
#------------------------------------------------------------------------------
#  战斗画面中,选择角色行动的窗口。
#==============================================================================
class Window_ActorCommand < Window_Command
  #--------------------------------------------------------------------------
  # ● 方向键移动光标时将鼠标移动到对应的光标位置
  #--------------------------------------------------------------------------
  def set_mouse_pos
    if viewport.nil?
      vp_x, vp_y = 0, 0
    else
      #vp_x = viewport.rect.x - viewport.ox
      vp_y = viewport.rect.y - viewport.oy
    end
    item_x1 = Graphics.width - width + standard_padding
    item_y1 = vp_y + y + standard_padding
    get_index = @index < 0 ? 0 : @index 
    row = get_index / col_max - top_row
    col = get_index % col_max
    new_x = item_x1 + item_width * (col + 0.5)
    new_y = item_y1 + item_height * (row + 0.5)
    Mouse.set_pos(new_x, new_y)
  end
end
 
#==============================================================================
# ■ Game_Player
#------------------------------------------------------------------------------
#  处理玩家人物的类。拥有事件启动的判定、地图的卷动等功能。
#   本类的实例请参考 $game_player 。
#==============================================================================
class Game_Player < Game_Character
  #--------------------------------------------------------------------------
  # ● 由方向移动(覆盖原方法)
  #--------------------------------------------------------------------------
  def move_by_input
    return if !movable? || $game_map.interpreter.running?
    if Input.dir4 > 0
      move_straight(Input.dir4) 
      reset_move_path
    else
      move_by_mouse
    end
  end
  #--------------------------------------------------------------------------
  # ● 非移动中的处理(覆盖原方法)
  #     last_moving : 此前是否正在移动
  #--------------------------------------------------------------------------
  def update_nonmoving(last_moving)
    return if $game_map.interpreter.running?
    if last_moving
      $game_party.on_player_walk
      return if check_touch_event
    end
    if movable? && Input.trigger?(:C)
      # 防止按下鼠标左键绘制路径时触发事件或载具切换
      return if Input.key_press?(0x01)
      return if get_on_off_vehicle
      return if check_action_event
    end
    update_encounter if last_moving
  end
  #--------------------------------------------------------------------------
  # ● 判定是否跑步状态(覆盖原方法)
  #--------------------------------------------------------------------------
  def dash?
    return false if @move_route_forcing
    return false if $game_map.disable_dash?
    return false if vehicle
    return Input.press?(:A) || @mouse_dash
  end
  #--------------------------------------------------------------------------
  # ● 初始化
  #--------------------------------------------------------------------------
  alias sion_mouse_initialize initialize
  def initialize
    sion_mouse_initialize
    reset_move_path
    @moveto_x = 0
    @moveto_y = 0
  end
  #--------------------------------------------------------------------------
  # ● 移动到指定位置
  #--------------------------------------------------------------------------
  alias sion_mouse_moveto moveto
  def moveto(x, y)
    sion_mouse_moveto(x, y)
    $mouse_move_sign.moveto( x, y )
  end
  #--------------------------------------------------------------------------
  # ● 更新
  #--------------------------------------------------------------------------
  alias sion_mouse_update update
  def update
    sion_mouse_update
    clear_unreachable_sign
  end
  #--------------------------------------------------------------------------
  # ● 处理卷动
  #--------------------------------------------------------------------------
  alias sion_mouse_update_scroll update_scroll
  def update_scroll(last_real_x, last_real_y)
    return if $game_map.scrolling? || $game_map.wait_scroll
    KsOfSion::New_Scroll ? new_update_scroll :
      sion_mouse_update_scroll(last_real_x, last_real_y)
  end
  #--------------------------------------------------------------------------
  # ● 重置移动路径相关信息
  #--------------------------------------------------------------------------
  def reset_move_path
    @mouse_dash = false
    @mouse_move_path = []
    $mouse_move_sign.transparent = true
  end
  #--------------------------------------------------------------------------
  # ● 新的卷动地图方法
  #--------------------------------------------------------------------------
  def new_update_scroll
    return if $game_message.busy? || $game_message.visible
    horz_speed = 2 ** @move_speed * KsOfSion::Map_Scroll_Spd / Graphics.width
    vert_speed = 2 ** @move_speed * KsOfSion::Map_Scroll_Spd / Graphics.height
    ax = $game_map.adjust_x( @real_x )
    ay = $game_map.adjust_y( @real_y )
    if    ay>center_y; $game_map.new_scroll_down (vert_speed * (ay - center_y))
    elsif ay<center_y; $game_map.new_scroll_up   (vert_speed * (center_y - ay))
    end
    if    ax>center_x; $game_map.new_scroll_right(horz_speed * (ax - center_x))
    elsif ax<center_x; $game_map.new_scroll_left (horz_speed * (center_x - ax))
    end
  end
  #--------------------------------------------------------------------------
  # ● 消除不能抵达图标
  #--------------------------------------------------------------------------
  def clear_unreachable_sign
    return if Input.key_press?(0x01)
    if $mouse_move_sign.direction == 4 && Mouse.dk_count % 20 == 1
      $mouse_move_sign.transparent = true
      $mouse_move_sign.direction = 2
    end
  end
  #--------------------------------------------------------------------------
  # ● 由鼠标移动
  #--------------------------------------------------------------------------
  def move_by_mouse
    unless @mouse_move_path.empty? # 移动路线数组不为空则执行移动
      dir = @mouse_move_path.shift
      if passable?(x, y, dir) && !@mouse_move_path.empty?
        move_straight(dir)
      elsif @mouse_move_path.empty? # 判断是否是最后一步
        x2 = $game_map.round_x_with_direction(x, dir)
        y2 = $game_map.round_y_with_direction(y, dir)
        move_straight(dir) unless dir.zero?
        unless @x == x2 && @y == y2 # 如果移动失败,检查是否启动前方事件
          check_event_trigger_there([0,1,2])
          get_on_off_vehicle unless $game_map.setup_starting_event
        end
        $mouse_move_sign.transparent = true if $mouse_move_sign.direction == 2
        @mouse_dash = false
      elsif @mouse_move_path[0].zero? # 目标点无法抵达,调整朝向→目标点
        @mouse_move_path.shift
        @direction = dir
        @mouse_dash = false
      else
        draw_move_path
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● 地图界面按下鼠标左键的处理
  #--------------------------------------------------------------------------
  def left_button_action
    @moveto_x = $game_map.mouse_map_x
    @moveto_y = $game_map.mouse_map_y
    return mouse_same_pos_action if @moveto_x == @x && @moveto_y == @y
    return if mouse_trigger_event?
    return unless drawable?
    draw_player_move_path
  end
  #--------------------------------------------------------------------------
  # ● 绘制玩家移动路径
  #--------------------------------------------------------------------------
  def draw_player_move_path
    @mouse_dash = true if Mouse.double_click?# 双击冲刺
    if Input.key_states[1] % 10 == 1 #按住鼠标左键10帧绘制1次路径
      $mouse_move_sign.moveto(@moveto_x, @moveto_y) # 移动路径点指示图
      for i in 1..4 # 判断目标点是否为角色周围四点
        if @x == $game_map.round_x_with_direction(@moveto_x, i * 2) &&
           @y == $game_map.round_y_with_direction(@moveto_y, i * 2)
          $mouse_move_sign.transparent = true
          @mouse_move_path = [10 - i * 2]
          return
        end
      end
      draw_move_path
    end
  end
  #--------------------------------------------------------------------------
  # ● 鼠标位置与玩家一致的处理
  #--------------------------------------------------------------------------
  def mouse_same_pos_action
    unless moving? || (vehicle && !vehicle.movable?)
      check_event_trigger_here([0]) # 判断是否触发重合点事件
      get_on_off_vehicle if !$game_map.setup_starting_event && 
        $game_map.airship.pos?(@x, @y)  # 判断是否要上、下飞艇
    end
  end
  #--------------------------------------------------------------------------
  # ● trigger 鼠标左键的处理
  #--------------------------------------------------------------------------
  def mouse_trigger_event?
    if Input.key_trigger?(0x01)
      $game_map.events_xy(@moveto_x, @moveto_y).each {|event|
        if event.mouse_start?
          event.start
          return true
        end
      }
    end
    return false
  end
  #--------------------------------------------------------------------------
  # ● 绘制移动路径 @array[move_directions...]
  #--------------------------------------------------------------------------
  def draw_move_path
    @mouse_move_path = 
    case @vehicle_type
    when :walk; draw_walk_path
    when :boat; draw_boat_path
    when :ship; draw_ship_path
    when :airship; draw_air_path
    end
  end
  #--------------------------------------------------------------------------
  # ● 判定是否可以绘制移动路径
  #--------------------------------------------------------------------------
  def drawable?
    return false if @move_route_forcing || @followers.gathering?
    return false if @vehicle_getting_on || @vehicle_getting_off
    return true
  end
  #--------------------------------------------------------------------------
  # ● 绘制行走路径 @array[move_directions...]
  #--------------------------------------------------------------------------
  def draw_walk_path
    # 准备绘制路径表格
    sheet = Table.new($game_map.width, $game_map.height)
    reversed_chase_path  = []; chase_path  = []
    reversed_chase_point = []; chase_point = []
    new_start_points = [x, y]; new_end_points = [@moveto_x, @moveto_y]
    sheet[x, y] = 1;           sheet[@moveto_x, @moveto_y] = 2
    reach_point = false
    step = 3
    loop do #loop1 开始填充表格
     draw_path = false
     check_points = new_start_points
     new_start_points = []
      loop do #loop2 从起点开始正向填充
        point_x = check_points.shift
        break if point_x == nil
        point_y = check_points.shift
        left_x  = $game_map.round_x(point_x - 1)
        right_x = $game_map.round_x(point_x + 1)
        up_y    = $game_map.round_y(point_y - 1)
        down_y  = $game_map.round_y(point_y + 1)
                    # 判断路径是否连通
        path_step = step - 1
        if sheet[left_x, point_y] == path_step     &&
           $game_map.passable?(left_x, point_y, 6) &&
           $game_map.passable?(point_x, point_y, 4)
          chase_path.push(4)
          chase_point = [left_x, point_y]
          reversed_chase_point = [point_x, point_y]
          reach_point = true; break
        elsif sheet[right_x, point_y] == path_step     &&
              $game_map.passable?(right_x, point_y, 4) &&
              $game_map.passable?(point_x, point_y, 6)
            chase_path.push(6)
            chase_point = [right_x, point_y]
            reversed_chase_point = [point_x, point_y]
            reach_point = true; break
        elsif sheet[point_x, up_y] == path_step     &&
              $game_map.passable?(point_x, up_y, 2) &&
              $game_map.passable?(point_x, point_y, 8)
            chase_path.push(8)
            chase_point = [point_x, up_y]
            reversed_chase_point = [point_x, point_y]
            reach_point = true; break
        elsif sheet[point_x, down_y] == path_step     &&
              $game_map.passable?(point_x, down_y, 8) &&
              $game_map.passable?(point_x, point_y, 2)
            chase_path.push(2)
            chase_point = [point_x, down_y]
            reversed_chase_point = [point_x, point_y]
            reach_point = true; break
        end
        # 以需要抵达该点的步数填充路径表格 #
        if sheet[left_x, point_y] == 0              &&
           $game_map.passable?(left_x, point_y, 6)  &&
           !collide_with_events?(left_x, point_y)   &&
           $game_map.passable?(point_x, point_y, 4) &&
           !collide_with_vehicles?(left_x, point_y) #judge_end
          sheet[left_x, point_y] = step
          draw_path = true
          new_start_points.push(left_x, point_y)
        end
        if sheet[right_x, point_y] == 0             &&
           $game_map.passable?(right_x, point_y, 4) &&
           !collide_with_events?(right_x, point_y)  &&
           $game_map.passable?(point_x, point_y, 6) &&
           !collide_with_vehicles?(right_x, point_y)#judge_end
          sheet[right_x, point_y] = step
          draw_path = true
          new_start_points.push(right_x, point_y)
        end
        if sheet[point_x, up_y] == 0                &&
           $game_map.passable?(point_x, up_y, 2)    &&
           !collide_with_events?(point_x, up_y)     &&
           $game_map.passable?(point_x, point_y, 8) &&
           !collide_with_vehicles?(point_x, up_y)   #judge_end
          sheet[point_x, up_y] = step
          draw_path = true
          new_start_points.push(point_x, up_y)
        end
        if sheet[point_x, down_y] == 0              &&
           $game_map.passable?(point_x, down_y, 8)  &&
           !collide_with_events?(point_x, down_y)   &&
           $game_map.passable?(point_x, point_y, 2) &&
           !collide_with_vehicles?(point_x, down_y) #judge_end
          sheet[point_x, down_y] = step
          draw_path = true
          new_start_points.push(point_x, down_y)
        end
      end#endOfLoop2
      break if !draw_path || reach_point
      draw_path = false
      check_points = new_end_points
      new_end_points = []
      step += 1
      break if step > KsOfSion::Break_Steps &&
               !Input.key_press?(KsOfSion::Find_Path_Key)
      loop do #loop3 从终点开始反向填充
        point_x = check_points.shift
        break if point_x == nil
        point_y = check_points.shift
        left_x  = $game_map.round_x(point_x - 1)
        right_x = $game_map.round_x(point_x + 1)
        up_y    = $game_map.round_y(point_y - 1)
        down_y  = $game_map.round_y(point_y + 1)
        # 判断路径是否连通
        path_step = step - 1
        if sheet[left_x, point_y] == path_step     &&
           $game_map.passable?(left_x, point_y, 6) &&
           $game_map.passable?(point_x, point_y, 4)
          chase_path.push(6)
          chase_point = [point_x, point_y]
          reversed_chase_point = [left_x, point_y]
          reach_point = true; break
        elsif sheet[right_x, point_y] == path_step     &&
              $game_map.passable?(right_x, point_y, 4) &&
              $game_map.passable?(point_x, point_y, 6)
            chase_path.push(4)
            chase_point = [point_x, point_y]
            reversed_chase_point = [right_x, point_y]
            reach_point = true; break
        elsif sheet[point_x, up_y] == path_step     &&
              $game_map.passable?(point_x, up_y, 2) &&
              $game_map.passable?(point_x, point_y, 8)
            chase_path.push(2)
            chase_point = [point_x, point_y]
            reversed_chase_point = [point_x, up_y]
            reach_point = true; break
        elsif sheet[point_x, down_y] == path_step     &&
              $game_map.passable?(point_x, down_y, 8) &&
              $game_map.passable?(point_x, point_y, 2)
            chase_path.push(8)
            chase_point = [point_x, point_y]
            reversed_chase_point = [point_x, down_y]
            reach_point = true; break
        end
        # 以需要抵达该点的步数填充路径表格 #
        if sheet[left_x, point_y] == 0              &&
           $game_map.passable?(left_x, point_y, 6)  &&
           !collide_with_events?(left_x, point_y)   &&
           $game_map.passable?(point_x, point_y, 4) &&
           !collide_with_vehicles?(left_x, point_y) #judge_end
          sheet[left_x, point_y] = step
          draw_path = true
          new_end_points.push(left_x, point_y)
        end
        if sheet[right_x, point_y] == 0             &&
           $game_map.passable?(right_x, point_y, 4) &&
           !collide_with_events?(right_x, point_y)  &&
           $game_map.passable?(point_x, point_y, 6) &&
           !collide_with_vehicles?(right_x, point_y)#judge_end
          sheet[right_x, point_y] = step
          draw_path = true
          new_end_points.push(right_x, point_y)
        end
        if sheet[point_x, up_y] == 0                &&
           $game_map.passable?(point_x, up_y, 2)    &&
           !collide_with_events?(point_x, up_y)     &&
           $game_map.passable?(point_x, point_y, 8) &&
           !collide_with_vehicles?(point_x, up_y)   #judge_end
          sheet[point_x, up_y] = step
          draw_path = true
          new_end_points.push(point_x, up_y)
        end
        if sheet[point_x, down_y] == 0              &&
           $game_map.passable?(point_x, down_y, 8)  &&
           !collide_with_events?(point_x, down_y)   &&
           $game_map.passable?(point_x, point_y, 2) &&
           !collide_with_vehicles?(point_x, down_y) #judge_end
          sheet[point_x, down_y] = step
          draw_path = true
          new_end_points.push(point_x, down_y)
        end
      end#endOfLoop3
      break if !draw_path || reach_point
      step += 1
    end #endOfLoop1 路径表格填充完毕
    $mouse_move_sign.transparent = false
    # 判断指定地点能否抵达
    if reach_point
      $mouse_move_sign.direction = 2
    else
      return not_reach_point
    end
    # 根据路径表格绘制最短移动路径(反向)
    steps = step / 2 * 2 + 1
    loop_times = step / 2
    point_x, point_y = reversed_chase_point[0], reversed_chase_point[1]
    for i in 1..loop_times # forLoop
    steps -= 2
    if (@moveto_x - point_x).abs < (@moveto_y - point_y).abs
      if    sheet[$game_map.round_x(point_x - 1), point_y] == steps         &&
            $game_map.passable?($game_map.round_x(point_x - 1), point_y, 6) &&
            $game_map.passable?(point_x, point_y, 4)                #judge_end
        reversed_chase_path.push(6)
        point_x = $game_map.round_x(point_x - 1)
      elsif sheet[$game_map.round_x(point_x + 1), point_y] == steps         &&
            $game_map.passable?($game_map.round_x(point_x + 1), point_y, 4) &&
            $game_map.passable?(point_x, point_y, 6)                #judge_end
        reversed_chase_path.push(4)
        point_x = $game_map.round_x(point_x + 1)
      elsif sheet[point_x, $game_map.round_y(point_y + 1)] == steps         &&
            $game_map.passable?(point_x, $game_map.round_y(point_y + 1), 8) &&
            $game_map.passable?(point_x, point_y, 2)                #judge_end
        reversed_chase_path.push(8)
        point_y = $game_map.round_y(point_y + 1)
      elsif sheet[point_x, $game_map.round_y(point_y - 1)] == steps         &&
            $game_map.passable?(point_x, $game_map.round_y(point_y - 1), 2) &&
            $game_map.passable?(point_x, point_y, 8)                #judge_end
        reversed_chase_path.push(2)
        point_y = $game_map.round_y(point_y - 1)
      end
    else
      if    sheet[point_x, $game_map.round_y(point_y + 1)] == steps         &&
            $game_map.passable?(point_x, $game_map.round_y(point_y + 1), 8) &&
            $game_map.passable?(point_x, point_y, 2)                #judge_end
        reversed_chase_path.push(8)
        point_y = $game_map.round_y(point_y + 1)
      elsif sheet[point_x, $game_map.round_y(point_y - 1)] == steps         &&
            $game_map.passable?(point_x, $game_map.round_y(point_y - 1), 2) &&
            $game_map.passable?(point_x, point_y, 8)                #judge_end
        reversed_chase_path.push(2)
        point_y = $game_map.round_y(point_y - 1)
      elsif sheet[$game_map.round_x(point_x - 1), point_y] == steps         &&
            $game_map.passable?($game_map.round_x(point_x - 1), point_y, 6) &&
            $game_map.passable?(point_x, point_y, 4)                #judge_end
        reversed_chase_path.push(6)
        point_x = $game_map.round_x(point_x - 1)
      elsif sheet[$game_map.round_x(point_x + 1), point_y] == steps         &&
            $game_map.passable?($game_map.round_x(point_x + 1), point_y, 4) &&
            $game_map.passable?(point_x, point_y, 6)                #judge_end
        reversed_chase_path.push(4)
        point_x = $game_map.round_x(point_x + 1)
      end
    end
    end #endOfForLoop
    # 根据路径表格绘制最短移动路径(正向)
    steps = step / 2 * 2
    loop_times = step / 2
    point_x, point_y = chase_point[0], chase_point[1]
    for i in 2..loop_times # forLoop
    steps -= 2
    if (@moveto_x - point_x).abs < (@moveto_y - point_y).abs
      if    sheet[point_x, $game_map.round_y(point_y + 1)] == steps         &&
            $game_map.passable?(point_x, $game_map.round_y(point_y + 1), 8) &&
            $game_map.passable?(point_x, point_y, 2)                #judge_end
        chase_path.push(2)
        point_y = $game_map.round_y(point_y + 1)
      elsif sheet[point_x, $game_map.round_y(point_y - 1)] == steps         &&
            $game_map.passable?(point_x, $game_map.round_y(point_y - 1), 2) &&
            $game_map.passable?(point_x, point_y, 8)                #judge_end
        chase_path.push(8)
        point_y = $game_map.round_y(point_y - 1)
      elsif sheet[$game_map.round_x(point_x - 1), point_y] == steps         &&
            $game_map.passable?($game_map.round_x(point_x - 1), point_y, 6) &&
            $game_map.passable?(point_x, point_y, 4)                #judge_end
        chase_path.push(4)
        point_x = $game_map.round_x(point_x - 1)
      elsif sheet[$game_map.round_x(point_x + 1), point_y] == steps         &&
            $game_map.passable?($game_map.round_x(point_x + 1), point_y, 4) &&
            $game_map.passable?(point_x, point_y, 6)                #judge_end
        chase_path.push(6)
        point_x = $game_map.round_x(point_x + 1)
      end
    else
      if    sheet[$game_map.round_x(point_x - 1), point_y] == steps         &&
            $game_map.passable?($game_map.round_x(point_x - 1), point_y, 6) &&
            $game_map.passable?(point_x, point_y, 4)                #judge_end
        chase_path.push(4)
        point_x = $game_map.round_x(point_x - 1)
      elsif sheet[$game_map.round_x(point_x + 1), point_y] == steps         &&
            $game_map.passable?($game_map.round_x(point_x + 1), point_y, 4) &&
            $game_map.passable?(point_x, point_y, 6)                #judge_end
        chase_path.push(6)
        point_x = $game_map.round_x(point_x + 1)
      elsif sheet[point_x, $game_map.round_y(point_y + 1)] == steps         &&
            $game_map.passable?(point_x, $game_map.round_y(point_y + 1), 8) &&
            $game_map.passable?(point_x, point_y, 2)                #judge_end
        chase_path.push(2)
        point_y = $game_map.round_y(point_y + 1)
      elsif sheet[point_x, $game_map.round_y(point_y - 1)] == steps         &&
            $game_map.passable?(point_x, $game_map.round_y(point_y - 1), 2) &&
            $game_map.passable?(point_x, point_y, 8)                #judge_end
        chase_path.push(8)
        point_y = $game_map.round_y(point_y - 1)
      end
    end
    end #endOfForLoop
    reversed_chase_path.reverse + chase_path
  end#walk
  ##
  def not_reach_point
    $mouse_move_sign.direction = 4
    dx = 0; dy = 0; dir = 0
    if @moveto_x - x > 0
      if @moveto_x - x > $game_map.width - @moveto_x + x &&
          $game_map.loop_vertical?
        dx = $game_map.width - @moveto_x + x; dir = 4
      else
        dx = @moveto_x - x; dir = 6
      end
    else
      if x - @moveto_x > $game_map.width - x + @moveto_x &&
          $game_map.loop_vertical?
        dx = $game_map.width - x + @moveto_x; dir = 6
      else
        dx = x - @moveto_x; dir = 4
      end
    end
    if @moveto_y - y > 0
      if @moveto_y - y > $game_map.height - @moveto_y + y &&
          $game_map.loop_horizontal?
        dy = $game_map.height - @moveto_y + y
        dir = 8 if dy > dx
      else
        dy = @moveto_y - y
        dir = 2 if dy > dx
      end
    else
      if y - @moveto_y > $game_map.height - y + @moveto_y &&
          $game_map.loop_horizontal?
        dy = $game_map.height - y + @moveto_y
        dir = 2 if dy > dx 
      else
        dy = y - @moveto_y
        dir = 8 if dy > dx
      end
    end
    return [dir, 0] # 0方向用于防止移动过程中触发事件
  end
  #--------------------------------------------------------------------------
  # ● 绘制boat的移动路径 @array[move_directions...]
  #--------------------------------------------------------------------------
  def draw_boat_path
    # 准备绘制路径表格
    sheet = Table.new($game_map.width, $game_map.height)
    reversed_chase_path  = []; chase_path  = []
    reversed_chase_point = []; chase_point = []
    new_start_points = [x, y]; new_end_points = [@moveto_x, @moveto_y]
    sheet[x, y] = 1;           sheet[@moveto_x, @moveto_y] = 2
    reach_point = false
    step = 3
    loop do #loop1 开始填充表格
     draw_path = false
     check_points = new_start_points
     new_start_points = []
      loop do #loop2 从起点开始正向填充
        point_x = check_points.shift
        break if point_x == nil
        point_y = check_points.shift
        left_x  = $game_map.round_x(point_x - 1)
        right_x = $game_map.round_x(point_x + 1)
        up_y    = $game_map.round_y(point_y - 1)
        down_y  = $game_map.round_y(point_y + 1)
                    # 判断路径是否连通
        path_step = step - 1
        if sheet[left_x, point_y] == path_step
          chase_path.push(4)
          chase_point = [left_x, point_y]
          reversed_chase_point = [point_x, point_y]
          reach_point = true; break
        elsif sheet[right_x, point_y] == path_step
            chase_path.push(6)
            chase_point = [right_x, point_y]
            reversed_chase_point = [point_x, point_y]
            reach_point = true; break
        elsif sheet[point_x, up_y] == path_step
            chase_path.push(8)
            chase_point = [point_x, up_y]
            reversed_chase_point = [point_x, point_y]
            reach_point = true; break
        elsif sheet[point_x, down_y] == path_step
            chase_path.push(2)
            chase_point = [point_x, down_y]
            reversed_chase_point = [point_x, point_y]
            reach_point = true; break
        end
        # 以需要抵达该点的步数填充路径表格 #
        if sheet[left_x, point_y] == 0                &&
           $game_map.boat_passable?(left_x, point_y)  &&
           !collide_with_events?(left_x, point_y)     &&
           !collide_with_vehicles?(left_x, point_y)   #judge_end
          sheet[left_x, point_y] = step
          draw_path = true
          new_start_points.push(left_x, point_y)
        end
        if sheet[right_x, point_y] == 0               &&
           $game_map.boat_passable?(right_x, point_y) &&
           !collide_with_events?(right_x, point_y)    &&
           !collide_with_vehicles?(right_x, point_y)  #judge_end
          sheet[right_x, point_y] = step
          draw_path = true
          new_start_points.push(right_x, point_y)
        end
        if sheet[point_x, up_y] == 0                  &&
           $game_map.boat_passable?(point_x, up_y)    &&
           !collide_with_events?(point_x, up_y)       &&
           !collide_with_vehicles?(point_x, up_y)     #judge_end
          sheet[point_x, up_y] = step
          draw_path = true
          new_start_points.push(point_x, up_y)
        end
        if sheet[point_x, down_y] == 0                &&
           $game_map.boat_passable?(point_x, down_y)  &&
           !collide_with_events?(point_x, down_y)     &&
           !collide_with_vehicles?(point_x, down_y)   #judge_end
          sheet[point_x, down_y] = step
          draw_path = true
          new_start_points.push(point_x, down_y)
        end
      end#endOfLoop2
      break if !draw_path || reach_point
      draw_path = false
      check_points = new_end_points
      new_end_points = []
      step += 1
      break if step > KsOfSion::Break_Steps &&
               !Input.key_press?(KsOfSion::Find_Path_Key)
      loop do #loop3 从终点开始反向填充
        point_x = check_points.shift
        break if point_x == nil
        point_y = check_points.shift
        left_x  = $game_map.round_x(point_x - 1)
        right_x = $game_map.round_x(point_x + 1)
        up_y    = $game_map.round_y(point_y - 1)
        down_y  = $game_map.round_y(point_y + 1)
        # 判断路径是否连通
        path_step = step - 1
        if sheet[left_x, point_y] == path_step
          chase_path.push(6)
          chase_point = [point_x, point_y]
          reversed_chase_point = [left_x, point_y]
          reach_point = true; break
        elsif sheet[right_x, point_y] == path_step
            chase_path.push(4)
            chase_point = [point_x, point_y]
            reversed_chase_point = [right_x, point_y]
            reach_point = true; break
        elsif sheet[point_x, up_y] == path_step
            chase_path.push(2)
            chase_point = [point_x, point_y]
            reversed_chase_point = [point_x, up_y]
            reach_point = true; break
        elsif sheet[point_x, down_y] == path_step
            chase_path.push(8)
            chase_point = [point_x, point_y]
            reversed_chase_point = [point_x, down_y]
            reach_point = true; break
        end
        # 以需要抵达该点的步数填充路径表格 #
        if sheet[left_x, point_y] == 0                &&
           $game_map.boat_passable?(left_x, point_y)  &&
           !collide_with_events?(left_x, point_y)     &&
           !collide_with_vehicles?(left_x, point_y)   #judge_end
          sheet[left_x, point_y] = step
          draw_path = true
          new_end_points.push(left_x, point_y)
        end
        if sheet[right_x, point_y] == 0               &&
           $game_map.boat_passable?(right_x, point_y) &&
           !collide_with_events?(right_x, point_y)    &&
           !collide_with_vehicles?(right_x, point_y)  #judge_end
          sheet[right_x, point_y] = step
          draw_path = true
          new_end_points.push(right_x, point_y)
        end
        if sheet[point_x, up_y] == 0                  &&
           $game_map.boat_passable?(point_x, up_y)    &&
           !collide_with_events?(point_x, up_y)       &&
           !collide_with_vehicles?(point_x, up_y)     #judge_end
          sheet[point_x, up_y] = step
          draw_path = true
          new_end_points.push(point_x, up_y)
        end
        if sheet[point_x, down_y] == 0                &&
           $game_map.boat_passable?(point_x, down_y)  &&
           !collide_with_events?(point_x, down_y)     &&
           !collide_with_vehicles?(point_x, down_y)   #judge_end
          sheet[point_x, down_y] = step
          draw_path = true
          new_end_points.push(point_x, down_y)
        end
      end#endOfLoop3
      break if !draw_path || reach_point
      step += 1
    end #endOfLoop1 路径表格填充完毕
    $mouse_move_sign.transparent = false
    # 判断指定地点能否抵达
    reach_point ? $mouse_move_sign.direction = 2 : (return not_reach_point)
    # 根据路径表格绘制最短移动路径(正向)
    steps = step / 2 * 2
    loop_times = step / 2
    point_x, point_y = chase_point[0], chase_point[1]
    for i in 2..loop_times # forLoop
    steps -= 2
    if (@moveto_x - point_x).abs < (@moveto_y - point_y).abs
      if    sheet[point_x, $game_map.round_y(point_y + 1)] == steps
        chase_path.push(2)
        point_y = $game_map.round_y(point_y + 1)
      elsif sheet[point_x, $game_map.round_y(point_y - 1)] == steps
        chase_path.push(8)
        point_y = $game_map.round_y(point_y - 1)
      elsif sheet[$game_map.round_x(point_x - 1), point_y] == steps
        chase_path.push(4)
        point_x = $game_map.round_x(point_x - 1)
      elsif sheet[$game_map.round_x(point_x + 1), point_y] == steps
        chase_path.push(6)
        point_x = $game_map.round_x(point_x + 1)
      end
    else
      if    sheet[$game_map.round_x(point_x - 1), point_y] == steps
        chase_path.push(4)
        point_x = $game_map.round_x(point_x - 1)
      elsif sheet[$game_map.round_x(point_x + 1), point_y] == steps
        chase_path.push(6)
        point_x = $game_map.round_x(point_x + 1)
      elsif sheet[point_x, $game_map.round_y(point_y + 1)] == steps
        chase_path.push(2)
        point_y = $game_map.round_y(point_y + 1)
      elsif sheet[point_x, $game_map.round_y(point_y - 1)] == steps
        chase_path.push(8)
        point_y = $game_map.round_y(point_y - 1)
      end
    end
    end #endOfForLoop
    # 如果指定点无法抵达或者登陆
    return not_reach_point unless landable?(@moveto_x, @moveto_y, chase_path)
    # 根据路径表格绘制最短移动路径(反向)
    steps = step / 2 * 2 + 1
    loop_times = step / 2
    point_x, point_y = reversed_chase_point[0], reversed_chase_point[1]
    for i in 1..loop_times # forLoop
    steps -= 2
    if (@moveto_x - point_x).abs < (@moveto_y - point_y).abs
      if    sheet[$game_map.round_x(point_x - 1), point_y] == steps
        reversed_chase_path.push(6)
        point_x = $game_map.round_x(point_x - 1)
      elsif sheet[$game_map.round_x(point_x + 1), point_y] == steps
        reversed_chase_path.push(4)
        point_x = $game_map.round_x(point_x + 1)
      elsif sheet[point_x, $game_map.round_y(point_y + 1)] == steps
        reversed_chase_path.push(8)
        point_y = $game_map.round_y(point_y + 1)
      elsif sheet[point_x, $game_map.round_y(point_y - 1)] == steps
        reversed_chase_path.push(2)
        point_y = $game_map.round_y(point_y - 1)
      end
    else
      if    sheet[point_x, $game_map.round_y(point_y + 1)] == steps
        reversed_chase_path.push(8)
        point_y = $game_map.round_y(point_y + 1)
      elsif sheet[point_x, $game_map.round_y(point_y - 1)] == steps
        reversed_chase_path.push(2)
        point_y = $game_map.round_y(point_y - 1)
      elsif sheet[$game_map.round_x(point_x - 1), point_y] == steps
        reversed_chase_path.push(6)
        point_x = $game_map.round_x(point_x - 1)
      elsif sheet[$game_map.round_x(point_x + 1), point_y] == steps
        reversed_chase_path.push(4)
        point_x = $game_map.round_x(point_x + 1)
      end
    end
    end #endOfForLoop
    return reversed_chase_path.reverse + chase_path
  end#boat
  #--------------------------------------------------------------------------
  # ● 绘制ship的移动路径 @array[move_directions...]
  #--------------------------------------------------------------------------
  def draw_ship_path
    # 准备绘制路径表格
    sheet = Table.new($game_map.width, $game_map.height)
    reversed_chase_path  = []; chase_path  = []
    reversed_chase_point = []; chase_point = []
    new_start_points = [x, y]; new_end_points = [@moveto_x, @moveto_y]
    sheet[x, y] = 1;           sheet[@moveto_x, @moveto_y] = 2
    reach_point = false
    step = 3
    loop do #loop1 开始填充表格
     draw_path = false
     check_points = new_start_points
     new_start_points = []
      loop do #loop2 从起点开始正向填充
        point_x = check_points.shift
        break if point_x == nil
        point_y = check_points.shift
        left_x  = $game_map.round_x(point_x - 1)
        right_x = $game_map.round_x(point_x + 1)
        up_y    = $game_map.round_y(point_y - 1)
        down_y  = $game_map.round_y(point_y + 1)
                    # 判断路径是否连通
        path_step = step - 1
        if sheet[left_x, point_y] == path_step
          chase_path.push(4)
          chase_point = [left_x, point_y]
          reversed_chase_point = [point_x, point_y]
          reach_point = true; break
        elsif sheet[right_x, point_y] == path_step
            chase_path.push(6)
            chase_point = [right_x, point_y]
            reversed_chase_point = [point_x, point_y]
            reach_point = true; break
        elsif sheet[point_x, up_y] == path_step
            chase_path.push(8)
            chase_point = [point_x, up_y]
            reversed_chase_point = [point_x, point_y]
            reach_point = true; break
        elsif sheet[point_x, down_y] == path_step
            chase_path.push(2)
            chase_point = [point_x, down_y]
            reversed_chase_point = [point_x, point_y]
            reach_point = true; break
        end
        # 以需要抵达该点的步数填充路径表格 #
        if sheet[left_x, point_y] == 0                &&
           $game_map.ship_passable?(left_x, point_y)  &&
           !collide_with_events?(left_x, point_y)     &&
           !collide_with_vehicles?(left_x, point_y)   #judge_end
          sheet[left_x, point_y] = step
          draw_path = true
          new_start_points.push(left_x, point_y)
        end
        if sheet[right_x, point_y] == 0               &&
           $game_map.ship_passable?(right_x, point_y) &&
           !collide_with_events?(right_x, point_y)    &&
           !collide_with_vehicles?(right_x, point_y)  #judge_end
          sheet[right_x, point_y] = step
          draw_path = true
          new_start_points.push(right_x, point_y)
        end
        if sheet[point_x, up_y] == 0                  &&
           $game_map.ship_passable?(point_x, up_y)    &&
           !collide_with_events?(point_x, up_y)       &&
           !collide_with_vehicles?(point_x, up_y)     #judge_end
          sheet[point_x, up_y] = step
          draw_path = true
          new_start_points.push(point_x, up_y)
        end
        if sheet[point_x, down_y] == 0                &&
           $game_map.ship_passable?(point_x, down_y)  &&
           !collide_with_events?(point_x, down_y)     &&
           !collide_with_vehicles?(point_x, down_y)   #judge_end
          sheet[point_x, down_y] = step
          draw_path = true
          new_start_points.push(point_x, down_y)
        end
      end#endOfLoop2
      break if !draw_path || reach_point
      draw_path = false
      check_points = new_end_points
      new_end_points = []
      step += 1
      break if step > KsOfSion::Break_Steps &&
               !Input.key_press?(KsOfSion::Find_Path_Key)
      loop do #loop3 从终点开始反向填充
        point_x = check_points.shift
        break if point_x == nil
        point_y = check_points.shift
        left_x  = $game_map.round_x(point_x - 1)
        right_x = $game_map.round_x(point_x + 1)
        up_y    = $game_map.round_y(point_y - 1)
        down_y  = $game_map.round_y(point_y + 1)
        # 判断路径是否连通
        path_step = step - 1
        if sheet[left_x, point_y] == path_step
          chase_path.push(6)
          chase_point = [point_x, point_y]
          reversed_chase_point = [left_x, point_y]
          reach_point = true; break
        elsif sheet[right_x, point_y] == path_step
            chase_path.push(4)
            chase_point = [point_x, point_y]
            reversed_chase_point = [right_x, point_y]
            reach_point = true; break
        elsif sheet[point_x, up_y] == path_step
            chase_path.push(2)
            chase_point = [point_x, point_y]
            reversed_chase_point = [point_x, up_y]
            reach_point = true; break
        elsif sheet[point_x, down_y] == path_step
            chase_path.push(8)
            chase_point = [point_x, point_y]
            reversed_chase_point = [point_x, down_y]
            reach_point = true; break
        end
        # 以需要抵达该点的步数填充路径表格 #
        if sheet[left_x, point_y] == 0                &&
           $game_map.ship_passable?(left_x, point_y)  &&
           !collide_with_events?(left_x, point_y)     &&
           !collide_with_vehicles?(left_x, point_y)   #judge_end
          sheet[left_x, point_y] = step
          draw_path = true
          new_end_points.push(left_x, point_y)
        end
        if sheet[right_x, point_y] == 0               &&
           $game_map.ship_passable?(right_x, point_y) &&
           !collide_with_events?(right_x, point_y)    &&
           !collide_with_vehicles?(right_x, point_y)  #judge_end
          sheet[right_x, point_y] = step
          draw_path = true
          new_end_points.push(right_x, point_y)
        end
        if sheet[point_x, up_y] == 0                  &&
           $game_map.ship_passable?(point_x, up_y)    &&
           !collide_with_events?(point_x, up_y)       &&
           !collide_with_vehicles?(point_x, up_y)     #judge_end
          sheet[point_x, up_y] = step
          draw_path = true
          new_end_points.push(point_x, up_y)
        end
        if sheet[point_x, down_y] == 0                &&
           $game_map.ship_passable?(point_x, down_y)  &&
           !collide_with_events?(point_x, down_y)     &&
           !collide_with_vehicles?(point_x, down_y)   #judge_end
          sheet[point_x, down_y] = step
          draw_path = true
          new_end_points.push(point_x, down_y)
        end
      end#endOfLoop3
      break if !draw_path || reach_point
      step += 1
    end #endOfLoop1 路径表格填充完毕
    $mouse_move_sign.transparent = false
    # 判断指定地点能否抵达
    reach_point ? $mouse_move_sign.direction = 2 : (return not_reach_point)
    # 根据路径表格绘制最短移动路径(正向)
    steps = step / 2 * 2
    loop_times = step / 2
    point_x, point_y = chase_point[0], chase_point[1]
    for i in 2..loop_times # forLoop
    steps -= 2
    if (@moveto_x - point_x).abs < (@moveto_y - point_y).abs
      if    sheet[point_x, $game_map.round_y(point_y + 1)] == steps
        chase_path.push(2)
        point_y = $game_map.round_y(point_y + 1)
      elsif sheet[point_x, $game_map.round_y(point_y - 1)] == steps
        chase_path.push(8)
        point_y = $game_map.round_y(point_y - 1)
      elsif sheet[$game_map.round_x(point_x - 1), point_y] == steps
        chase_path.push(4)
        point_x = $game_map.round_x(point_x - 1)
      elsif sheet[$game_map.round_x(point_x + 1), point_y] == steps
        chase_path.push(6)
        point_x = $game_map.round_x(point_x + 1)
      end
    else
      if    sheet[$game_map.round_x(point_x - 1), point_y] == steps
        chase_path.push(4)
        point_x = $game_map.round_x(point_x - 1)
      elsif sheet[$game_map.round_x(point_x + 1), point_y] == steps
        chase_path.push(6)
        point_x = $game_map.round_x(point_x + 1)
      elsif sheet[point_x, $game_map.round_y(point_y + 1)] == steps
        chase_path.push(2)
        point_y = $game_map.round_y(point_y + 1)
      elsif sheet[point_x, $game_map.round_y(point_y - 1)] == steps
        chase_path.push(8)
        point_y = $game_map.round_y(point_y - 1)
      end
    end
    end #endOfForLoop
    # 如果指定点无法抵达或者登陆
    return not_reach_point unless landable?(@moveto_x, @moveto_y, chase_path)
    # 根据路径表格绘制最短移动路径(反向)
    steps = step / 2 * 2 + 1
    loop_times = step / 2
    point_x, point_y = reversed_chase_point[0], reversed_chase_point[1]
    for i in 1..loop_times # forLoop
    steps -= 2
    if (@moveto_x - point_x).abs < (@moveto_y - point_y).abs
      if    sheet[$game_map.round_x(point_x - 1), point_y] == steps
        reversed_chase_path.push(6)
        point_x = $game_map.round_x(point_x - 1)
      elsif sheet[$game_map.round_x(point_x + 1), point_y] == steps
        reversed_chase_path.push(4)
        point_x = $game_map.round_x(point_x + 1)
      elsif sheet[point_x, $game_map.round_y(point_y + 1)] == steps
        reversed_chase_path.push(8)
        point_y = $game_map.round_y(point_y + 1)
      elsif sheet[point_x, $game_map.round_y(point_y - 1)] == steps
        reversed_chase_path.push(2)
        point_y = $game_map.round_y(point_y - 1)
      end
    else
      if    sheet[point_x, $game_map.round_y(point_y + 1)] == steps
        reversed_chase_path.push(8)
        point_y = $game_map.round_y(point_y + 1)
      elsif sheet[point_x, $game_map.round_y(point_y - 1)] == steps
        reversed_chase_path.push(2)
        point_y = $game_map.round_y(point_y - 1)
      elsif sheet[$game_map.round_x(point_x - 1), point_y] == steps
        reversed_chase_path.push(6)
        point_x = $game_map.round_x(point_x - 1)
      elsif sheet[$game_map.round_x(point_x + 1), point_y] == steps
        reversed_chase_path.push(4)
        point_x = $game_map.round_x(point_x + 1)
      end
    end
    end #endOfForLoop
    return reversed_chase_path.reverse + chase_path
  end#ship
  #--------------------------------------------------------------------------
  # ● 绘制airship的移动路径 @array[move_directions...]
  #--------------------------------------------------------------------------
  def draw_air_path
    $mouse_move_sign.transparent = false
    # 准备绘制路径表格
    sheet = Table.new($game_map.width, $game_map.height)
    new_check_point = [x, y]; sheet[x, y] = 1
    reach_point = false;      step = 2
    loop do #loop1
     check_point = new_check_point
     new_check_point = []
      loop do #loop2
        point_x = check_point.shift
        break if point_x == nil
        point_y = check_point.shift
        if point_x == @moveto_x && point_y == @moveto_y
          reach_point = true; break
        end
        left_x  = $game_map.round_x(point_x - 1)
        right_x = $game_map.round_x(point_x + 1)
        up_y    = $game_map.round_y(point_y - 1)
        down_y  = $game_map.round_y(point_y + 1) 
        # 以需要抵达该点的步数填充路径表格 #
        if sheet[left_x, point_y] == 0
          sheet[left_x, point_y] = step
          new_check_point.push(left_x, point_y)
        end
        if sheet[right_x, point_y] == 0
          sheet[right_x, point_y] = step
          new_check_point.push(right_x, point_y)
        end
        if sheet[point_x, up_y] == 0
          sheet[point_x, up_y] = step
          new_check_point.push(point_x, up_y)
        end
        if sheet[point_x, down_y] == 0
          sheet[point_x, down_y] = step
          new_check_point.push(point_x, down_y)
        end
      end#endOfLoop2
      break if reach_point
      step += 1
    end #endOfLoop1
    # 根据路径表格绘制最短移动路径 #
    reversed_chase_path = []; step -= 1
    point_x, point_y = @moveto_x, @moveto_y
    for i in 2..step
    step -= 1
    if (@moveto_x - point_x).abs < (@moveto_y - point_y).abs
      if    sheet[$game_map.round_x(point_x - 1), point_y] == step
        reversed_chase_path.push(6)
        point_x = $game_map.round_x(point_x - 1)
      elsif sheet[$game_map.round_x(point_x + 1), point_y] == step
        reversed_chase_path.push(4)
        point_x = $game_map.round_x(point_x + 1)
      elsif sheet[point_x, $game_map.round_y(point_y + 1)] == step
        reversed_chase_path.push(8)
        point_y = $game_map.round_y(point_y + 1)
      elsif sheet[point_x, $game_map.round_y(point_y - 1)] == step
        reversed_chase_path.push(2)
        point_y = $game_map.round_y(point_y - 1)
      end
    else
      if    sheet[point_x, $game_map.round_y(point_y + 1)] == step
        reversed_chase_path.push(8)
        point_y = $game_map.round_y(point_y + 1)
      elsif sheet[point_x, $game_map.round_y(point_y - 1)] == step
        reversed_chase_path.push(2)
        point_y = $game_map.round_y(point_y - 1)
      elsif sheet[$game_map.round_x(point_x - 1), point_y] == step
        reversed_chase_path.push(6)
        point_x = $game_map.round_x(point_x - 1)
      elsif sheet[$game_map.round_x(point_x + 1), point_y] == step
        reversed_chase_path.push(4)
        point_x = $game_map.round_x(point_x + 1)
      end
    end
    end #endOfForLoop 
    return reversed_chase_path.reverse
  end#airship
  #--------------------------------------------------------------------------
  # ● 判断目标点是否能抵达、登陆,用于船只路径绘制
  #--------------------------------------------------------------------------
  def landable?(x, y, path)
    case @vehicle_type
      when :ship; return $game_map.ship_passable?(x, y) ||
        $game_map.passable?(x, y, 10 - path[-1])
      when :boat; return $game_map.boat_passable?(x, y) ||
        $game_map.passable?(x, y, 10 - path[-1])
    end
  end
end
 
#==============================================================================
# ■ Game_Map
#------------------------------------------------------------------------------
#  管理地图的类。拥有卷动地图以及判断通行度的功能。
#   本类的实例请参考 $game_map 。
#==============================================================================
class Game_Map
  #--------------------------------------------------------------------------
  # ● 初始化对象
  #--------------------------------------------------------------------------
  alias sion_mouse_initialize initialize
  def initialize
    sion_mouse_initialize
    creat_move_sign  ###
    set_constants
  end
  #--------------------------------------------------------------------------
  # ● 更新画面
  #     main : 事件解释器更新的标志
  #--------------------------------------------------------------------------
  alias sion_mouse_update update
  def update(main = false)
    sion_mouse_update(main)
    update_move_sign
  end
  #--------------------------------------------------------------------------
  # ● 设置显示位置
  #--------------------------------------------------------------------------
  alias sion_mouse_set_display_pos set_display_pos
  def set_display_pos(x, y)
    sion_mouse_set_display_pos(x, y)
    @_display_y_ = @display_y
    @_display_x_ = @display_x
  end
  #--------------------------------------------------------------------------
  # ● 创建显示路径点的事件
  #--------------------------------------------------------------------------
  def creat_move_sign
    $mouse_move_sign = Move_Sign.new
  end
  #--------------------------------------------------------------------------
  # ● 更新显示路径点的事件
  #--------------------------------------------------------------------------
  def set_constants
    @mouse_pos_setted = true
    @set_pos_prepared = false
    @mouse_old_x = 0
    @mouse_old_y = 0
  end
  #--------------------------------------------------------------------------
  # ● 更新显示路径点的事件
  #--------------------------------------------------------------------------
  def update_move_sign
    $mouse_move_sign.update
  end
  #--------------------------------------------------------------------------
  # ● 获取鼠标位于的地图块的x、y坐标
  #--------------------------------------------------------------------------
  def mouse_map_x
    round_x((@display_x + Mouse.x / 32.0).to_i)
  end
  def mouse_map_y
    round_y((@display_y + Mouse.y / 32.0).to_i)
  end
  #--------------------------------------------------------------------------
  # ● 返回地图画面时重设鼠标坐标
  #--------------------------------------------------------------------------
  def reset_mouse_pos
    return if @mouse_pos_setted
    Mouse.set_pos(@mouse_old_x, @mouse_old_y)
    @mouse_pos_setted = true
    @set_pos_prepared = false
  end
  #--------------------------------------------------------------------------
  # ● 重设鼠标的坐标
  #--------------------------------------------------------------------------
  def prepare_reset_mouse_pos
    return if @set_pos_prepared
    @mouse_pos_setted = false
    @mouse_old_x = Mouse.x
    @mouse_old_y = Mouse.y
    @set_pos_prepared = true
  end
  #--------------------------------------------------------------------------
  # ● 向下卷动
  #--------------------------------------------------------------------------
  def new_scroll_down(distance)
    if loop_vertical?
      @_display_y_ += distance
      @_display_y_ %= @map.height
      @parallax_y += distance if @parallax_loop_y
    else
      last_y = @_display_y_
      @_display_y_ = [@_display_y_ + distance, height - screen_tile_y].min
      @parallax_y += @_display_y_ - last_y
    end
    @display_y = (@_display_y_ * 32).round / 32.0
  end
  #--------------------------------------------------------------------------
  # ● 向左卷动
  #--------------------------------------------------------------------------
  def new_scroll_left(distance)
    if loop_horizontal?
      @_display_x_ += @map.width - distance
      @_display_x_ %= @map.width 
      @parallax_x -= distance if @parallax_loop_x
    else
      last_x = @_display_x_
      @_display_x_ = [@_display_x_ - distance, 0].max
      @parallax_x += @_display_x_ - last_x
    end
    @display_x = (@_display_x_ * 32).round / 32.0
  end
  #--------------------------------------------------------------------------
  # ● 向右卷动
  #--------------------------------------------------------------------------
  def new_scroll_right(distance)
    if loop_horizontal?
      @_display_x_ += distance
      @_display_x_ %= @map.width
      @parallax_x += distance if @parallax_loop_x
    else
      last_x = @_display_x_
      @_display_x_ = [@_display_x_ + distance, (width - screen_tile_x)].min
      @parallax_x += @_display_x_ - last_x
    end
    @display_x = (@_display_x_ * 32).round / 32.0
  end
  #--------------------------------------------------------------------------
  # ● 向上卷动
  #--------------------------------------------------------------------------
  def new_scroll_up(distance)
    if loop_vertical?
      @_display_y_ += @map.height - distance
      @_display_y_ %= @map.height
      @parallax_y -= distance if @parallax_loop_y
    else
      last_y = @_display_y_
      @_display_y_ = [@_display_y_ - distance, 0].max
      @parallax_y += @_display_y_ - last_y
    end
    @display_y = (@_display_y_ * 32).round / 32.0
  end
end
 
#==============================================================================
# ■ Spriteset_Map
#------------------------------------------------------------------------------
#  处理地图画面精灵和图块的类。本类在 Scene_Map 类的内部使用。
#==============================================================================
class Spriteset_Map
  #--------------------------------------------------------------------------
  # ● 生成路径点精灵
  #--------------------------------------------------------------------------
  alias sion_mouse_create_characters create_characters
  def create_characters
    sion_mouse_create_characters
    @character_sprites.push(Sprite_Character.new(@viewport1, $mouse_move_sign))
  end
end
 
#==============================================================================
# ■ SceneManager
#==============================================================================
class << SceneManager
  alias sion_mouse_snapshot_for_background snapshot_for_background
  def snapshot_for_background
    Mouse.sprite.visible = false
    sion_mouse_snapshot_for_background
    Mouse.sprite.visible = true
  end
end
#==============================================================================
# ■ Scene_Map
#------------------------------------------------------------------------------
#  地图画面
#==============================================================================
class Scene_Map
  #--------------------------------------------------------------------------
  # ● 画面更新
  #--------------------------------------------------------------------------
  alias sion_mouse_update_scene update_scene
  def update_scene
    sion_mouse_update_scene
    update_mouse_action unless scene_changing? || $game_map.interpreter.running?
  end
  #--------------------------------------------------------------------------
  # ● 场所移动前的处理
  #--------------------------------------------------------------------------
  alias sion_mouse_pre_transfer pre_transfer
  def pre_transfer
    $game_player.reset_move_path
    sion_mouse_pre_transfer
  end
  #--------------------------------------------------------------------------
  # ● 监听鼠标左键的按下
  #--------------------------------------------------------------------------
  def update_mouse_action
    $game_player.left_button_action if Input.key_press?(0x01)
  end
end
 
#==============================================================================
# ■ Scene_File
#------------------------------------------------------------------------------
#  存档画面和读档画面共同的父类
#==============================================================================
class Scene_File < Scene_MenuBase
  #--------------------------------------------------------------------------
  # ● 开始处理
  #--------------------------------------------------------------------------
  alias sion_mouse_start start
  def start
    sion_mouse_start
    @move_state = 0
    set_mouse_pos
  end
  #--------------------------------------------------------------------------
  # ● 更新画面
  #--------------------------------------------------------------------------
  alias sion_mouse_update update
  def update
    sion_mouse_update
    Input.dir4.zero? ? set_cursor : set_mouse_pos
  end
  #--------------------------------------------------------------------------
  # ● 更新光标
  #--------------------------------------------------------------------------
  def set_cursor
    @move_state += 1
    last_index = @index
    if mouse_which_window == -2
      if (@move_state - 1) % 6 == 0
        @index = (@index + 1) % item_max if @index < item_max - 1
      end
    elsif mouse_which_window == -1
      if (@move_state - 1) % 6 == 0
        @index = (@index - 1 + item_max) % item_max if @index > 0
      end
    else
      @move_state = 0
      @index = top_index + mouse_which_window
    end
    ensure_cursor_visible
    if @index != last_index
      @savefile_windows[last_index].selected = false
      @savefile_windows[@index].selected = true
    end
  end
  #--------------------------------------------------------------------------
  # ● 判断鼠标位于哪个窗口
  #--------------------------------------------------------------------------
  def mouse_which_window
    mouse_x = Mouse.x
    mouse_y = Mouse.y
    if mouse_y < @help_window.height + 14
      mouse_row = -1
    elsif mouse_y > Graphics.height - 14
      mouse_row = -2
    else
      mouse_row = 4 * (mouse_y - @help_window.height) /
        (Graphics.height - @help_window.height)
    end
    return mouse_row
  end
  #--------------------------------------------------------------------------
  # ● 方向键移动光标时将鼠标移动到对应的光标位置
  #--------------------------------------------------------------------------
  def set_mouse_pos
    new_x = 40
    new_y = @help_window.height + savefile_height * (@index - top_index) + 24
    Mouse.set_pos(new_x, new_y)
  end
end
 
#==============================================================================
# ■ Game_Event
#------------------------------------------------------------------------------
#  处理事件的类。拥有条件判断、事件页的切换、并行处理、执行事件等功能。
#   在 Game_Map 类的内部使用。
#==============================================================================
class Game_Event < Game_Character
  alias_method :sion_mouse_start, :start
  alias_method :sion_mouse_setup_page, :setup_page
  def start
    return if mouse_start? && !Input.key_press?(0x01)
    sion_mouse_start
  end
  def mouse_start?
    @mouse_start
  end
  def setup_page(p)
    sion_mouse_setup_page(p)
    sion_mouse_read_event_notes
  end
  def sion_mouse_read_event_notes
    @mouse_start = false
    @list.each {|cmd| break if sion_mouse_scan_list(cmd)} unless empty?
  end
  def sion_mouse_scan_list(cmd)
    return false unless cmd.code == 108 || cmd.code == 408
    return @mouse_start = cmd.parameters[0].include?("鼠标启动")
  end
end
 
#encoding:utf-8
#==============================================================================
# ■ BattleManager
#------------------------------------------------------------------------------
#  战斗过程的管理器。
#==============================================================================
class << BattleManager
  alias_method :sion_mouse_on_encounter, :on_encounter
  # 遇敌后重置移动路径
  def on_encounter
    $game_player.reset_move_path
    sion_mouse_on_encounter
  end
end
 
# v3.03 卷动地图优化
class Game_Interpreter
  alias_method :sion_mouse_command_204, :command_204
  def command_204
    sion_mouse_command_204
    case next_event_code
    when 204
      Fiber.yield while $game_map.scrolling?
      @index += 1
      execute_command
    when 230
      $game_map.wait_scroll = true
      @index += 1
      execute_command
      $game_map.wait_scroll = false
    end
  end
  #230 wait
end
 
class Game_Map
  attr_accessor :wait_scroll
  # 覆盖原方法
  def update(main = false)
    refresh if @need_refresh
    update_scroll
    update_interpreter if main
    update_events
    update_vehicles
    update_parallax
    @screen.update
  end
end
 
 
if $SINOVA #验证组件完整性
  if $SINOVA[:mouseBase]
    if $SINOVA[:mouseBase] >= 3.00     #所需组件版本
      $SINOVA[:mouseBaseSystem] = 3.01 #当前组件版本
    else
      msgbox "Sion_MouseBase 版本过低,需 3.00 以上"
      exit
    end
  else
    msgbox "Nova_TypeIn 需置于 Sion_MouseBase 脚本之下"
    exit
  end
else
  msgbox "Nova_TypeIn 需置于 NovaBase 脚本之下"
  exit
end