#==============================================================================
#  Game_Map
#------------------------------------------------------------------------------
# @}bvNXłBXN[ʍs\Ȃǂ̋@\Ă܂B
# ̃NX̃CX^X $game_map ŎQƂ܂B
#==============================================================================

class Game_Map
  #--------------------------------------------------------------------------
  #  JCX^Xϐ
  #--------------------------------------------------------------------------
  attr_reader   :screen                   # }bvʂ̏
  attr_reader   :interpreter              # }bvCxgpC^v^
  attr_reader   :display_x                # \ X W * 256
  attr_reader   :display_y                # \ Y W * 256
  attr_reader   :parallax_name            # i t@C
  attr_reader   :passages                 # ʍs e[u
  attr_reader   :events                   # Cxg
  attr_reader   :vehicles                 # 蕨
  attr_accessor :need_refresh             # tbVvtO
  #--------------------------------------------------------------------------
  #  IuWFNg
  #--------------------------------------------------------------------------
  def initialize
    @screen = Game_Screen.new
    @interpreter = Game_Interpreter.new(0, true)
    @map_id = 0
    @display_x = 0
    @display_y = 0
    create_vehicles
  end
  #--------------------------------------------------------------------------
  #  ZbgAbv
  #     map_id : }bv ID
  #--------------------------------------------------------------------------
  def setup(map_id)
    @map_id = map_id
    @map = load_data(sprintf("Data/Map%03d.rvdata", @map_id))
    @display_x = 0
    @display_y = 0
    @passages = $data_system.passages
    referesh_vehicles
    setup_events
    setup_scroll
    setup_parallax
    @need_refresh = false
  end
  #--------------------------------------------------------------------------
  #  蕨̍쐬
  #--------------------------------------------------------------------------
  def create_vehicles
    @vehicles = []
    @vehicles[0] = Game_Vehicle.new(0)    # ^D
    @vehicles[1] = Game_Vehicle.new(1)    # ^D
    @vehicles[2] = Game_Vehicle.new(2)    # sD
  end
  #--------------------------------------------------------------------------
  #  蕨̃tbV
  #--------------------------------------------------------------------------
  def referesh_vehicles
    for vehicle in @vehicles
      vehicle.refresh
    end
  end
  #--------------------------------------------------------------------------
  #  ^D̎擾
  #--------------------------------------------------------------------------
  def boat
    return @vehicles[0]
  end
  #--------------------------------------------------------------------------
  #  ^D̎擾
  #--------------------------------------------------------------------------
  def ship
    return @vehicles[1]
  end
  #--------------------------------------------------------------------------
  #  sD̎擾
  #--------------------------------------------------------------------------
  def airship
    return @vehicles[2]
  end
  #--------------------------------------------------------------------------
  #  Cxg̃ZbgAbv
  #--------------------------------------------------------------------------
  def setup_events
    @events = {}          # }bvCxg
    for i in @map.events.keys
      @events[i] = Game_Event.new(@map_id, @map.events[i])
      #T14-030 ADD--->
      @events[i].exop = Ex.parse_exop(@map.events[i].name)
      #<--------------
    end
    @common_events = {}   # RCxg
    for i in 1...$data_common_events.size
      @common_events[i] = Game_CommonEvent.new(i)
    end
  end
  #--------------------------------------------------------------------------
  #  XN[̃ZbgAbv
  #--------------------------------------------------------------------------
  def setup_scroll
    @scroll_direction = 2
    @scroll_rest = 0
    @scroll_speed = 4
    @margin_x = (width - 17) * 256 / 2      # ʔ\̉ / 2
    @margin_y = (height - 13) * 256 / 2     # ʔ\̏c / 2
  end
  #--------------------------------------------------------------------------
  #  ĩZbgAbv
  #--------------------------------------------------------------------------
  def setup_parallax
    @parallax_name = @map.parallax_name
    @parallax_loop_x = @map.parallax_loop_x
    @parallax_loop_y = @map.parallax_loop_y
    @parallax_sx = @map.parallax_sx
    @parallax_sy = @map.parallax_sy
    @parallax_x = 0
    @parallax_y = 0
  end
  #--------------------------------------------------------------------------
  #  \ʒu̐ݒ
  #     x : V\ X W (*256)
  #     y : V\ Y W (*256)
  #--------------------------------------------------------------------------
  def set_display_pos(x, y)
    @display_x = (x + @map.width * 256) % (@map.width * 256)
    @display_y = (y + @map.height * 256) % (@map.height * 256)
    @parallax_x = x
    @parallax_y = y
  end
  #--------------------------------------------------------------------------
  #  i\ X W̌vZ
  #     bitmap : irbg}bv
  #--------------------------------------------------------------------------
  def calc_parallax_x(bitmap)
    if bitmap == nil
      return 0
    elsif @parallax_loop_x
      return @parallax_x / 16
    elsif loop_horizontal?
      return 0
    else
      w1 = bitmap.width - 544
      w2 = @map.width * 32 - 544
      if w1 <= 0 or w2 <= 0
        return 0
      else
        return @parallax_x * w1 / w2 / 8
      end
    end
  end
  #--------------------------------------------------------------------------
  #  i\ Y W̌vZ
  #     bitmap : irbg}bv
  #--------------------------------------------------------------------------
  def calc_parallax_y(bitmap)
    if bitmap == nil
      return 0
    elsif @parallax_loop_y
      return @parallax_y / 16
    elsif loop_vertical?
      return 0
    else
      h1 = bitmap.height - 416
      h2 = @map.height * 32 - 416
      if h1 <= 0 or h2 <= 0
        return 0
      else
        return @parallax_y * h1 / h2 / 8
      end
    end
  end
  #--------------------------------------------------------------------------
  #  }bv ID ̎擾
  #--------------------------------------------------------------------------
  def map_id
    return @map_id
  end
  #--------------------------------------------------------------------------
  #  ̎擾
  #--------------------------------------------------------------------------
  def width
    return @map.width
  end
  #--------------------------------------------------------------------------
  #  ̎擾
  #--------------------------------------------------------------------------
  def height
    return @map.height
  end
  #--------------------------------------------------------------------------
  #  Ƀ[v邩H
  #--------------------------------------------------------------------------
  def loop_horizontal?
    return (@map.scroll_type == 2 or @map.scroll_type == 3)
  end
  #--------------------------------------------------------------------------
  #  cɃ[v邩H
  #--------------------------------------------------------------------------
  def loop_vertical?
    return (@map.scroll_type == 1 or @map.scroll_type == 3)
  end
  #--------------------------------------------------------------------------
  #  _bV֎~ۂ̎擾
  #--------------------------------------------------------------------------
  def disable_dash?
    return @map.disable_dashing
  end
  #--------------------------------------------------------------------------
  #  GJEgXg̎擾
  #--------------------------------------------------------------------------
  def encounter_list
    return @map.encounter_list
  end
  #--------------------------------------------------------------------------
  #  GJEg̎擾
  #--------------------------------------------------------------------------
  def encounter_step
    return @map.encounter_step
  end
  #--------------------------------------------------------------------------
  #  }bvf[^̎擾
  #--------------------------------------------------------------------------
  def data
    return @map.data
  end
  #--------------------------------------------------------------------------
  #  \W X W̌vZ
  #     x : X W
  #--------------------------------------------------------------------------
  def adjust_x(x)
    if loop_horizontal? and x < @display_x - @margin_x
      return x - @display_x + @map.width * 256
    else
      return x - @display_x
    end
  end
  #--------------------------------------------------------------------------
  #  \W Y W̌vZ
  #     y : Y W
  #--------------------------------------------------------------------------
  def adjust_y(y)
    if loop_vertical? and y < @display_y - @margin_y
      return y - @display_y + @map.height * 256
    else
      return y - @display_y
    end
  end
  #--------------------------------------------------------------------------
  #  [v␳ X WvZ
  #     x : X W
  #--------------------------------------------------------------------------
  def round_x(x)
    if loop_horizontal?
      return (x + width) % width
    else
      return x
    end
  end
  #--------------------------------------------------------------------------
  #  [v␳ Y WvZ
  #     y : Y W
  #--------------------------------------------------------------------------
  def round_y(y)
    if loop_vertical?
      return (y + height) % height
    else
      return y
    end
  end
  #--------------------------------------------------------------------------
  #  ̕ 1 }X炵 X W̌vZ
  #     x         : X W
  #     direction :  (2,4,6,8)
  #--------------------------------------------------------------------------
  def x_with_direction(x, direction)
    return round_x(x + (direction == 6 ? 1 : direction == 4 ? -1 : 0))
  end
  #--------------------------------------------------------------------------
  #  ̕ 1 }X炵 Y W̌vZ
  #     y         : Y W
  #     direction :  (2,4,6,8)
  #--------------------------------------------------------------------------
  def y_with_direction(y, direction)
    return round_y(y + (direction == 2 ? 1 : direction == 8 ? -1 : 0))
  end
  #--------------------------------------------------------------------------
  #  wWɑ݂Cxg̔z擾
  #     x : X W
  #     y : Y W
  #--------------------------------------------------------------------------
  def events_xy(x, y)
    result = []
    for event in $game_map.events.values
      result.push(event) if event.pos?(x, y)
    end
    return result
  end
  #--------------------------------------------------------------------------
  #  BGM / BGS ؂ւ
  #--------------------------------------------------------------------------
  def autoplay
    @map.bgm.play if @map.autoplay_bgm
    @map.bgs.play if @map.autoplay_bgs
  end
  #--------------------------------------------------------------------------
  #  tbV
  #--------------------------------------------------------------------------
  def refresh
    if @map_id > 0
      for event in @events.values
        event.refresh
      end
      for common_event in @common_events.values
        common_event.refresh
      end
    end
    @need_refresh = false
  end
  #--------------------------------------------------------------------------
  #  ɃXN[
  #     distance : XN[鋗
  #--------------------------------------------------------------------------
  def scroll_down(distance)
    if loop_vertical?
      @display_y += distance
      @display_y %= @map.height * 256
      @parallax_y += distance
    else
      last_y = @display_y
      @display_y = [@display_y + distance, (height - 13) * 256].min
      @parallax_y += @display_y - last_y
    end
  end
  #--------------------------------------------------------------------------
  #  ɃXN[
  #     distance : XN[鋗
  #--------------------------------------------------------------------------
  def scroll_left(distance)
    if loop_horizontal?
      @display_x += @map.width * 256 - distance
      @display_x %= @map.width * 256
      @parallax_x -= distance
    else
      last_x = @display_x
      @display_x = [@display_x - distance, 0].max
      @parallax_x += @display_x - last_x
    end
  end
  #--------------------------------------------------------------------------
  #  EɃXN[
  #     distance : XN[鋗
  #--------------------------------------------------------------------------
  def scroll_right(distance)
    if loop_horizontal?
      @display_x += distance
      @display_x %= @map.width * 256
      @parallax_x += distance
    else
      last_x = @display_x
      @display_x = [@display_x + distance, (width - 17) * 256].min
      @parallax_x += @display_x - last_x
    end
  end
  #--------------------------------------------------------------------------
  #  ɃXN[
  #     distance : XN[鋗
  #--------------------------------------------------------------------------
  def scroll_up(distance)
    if loop_vertical?
      @display_y += @map.height * 256 - distance
      @display_y %= @map.height * 256
      @parallax_y -= distance
    else
      last_y = @display_y
      @display_y = [@display_y - distance, 0].max
      @parallax_y += @display_y - last_y
    end
  end
  #--------------------------------------------------------------------------
  #  LW
  #     x : X W
  #     y : Y W
  #--------------------------------------------------------------------------
  def valid?(x, y)
    return (x >= 0 and x < width and y >= 0 and y < height)
  end
  #--------------------------------------------------------------------------
  #  ʍs\
  #     x    : X W
  #     y    : Y W
  #     flag : ׂʍs֎~rbg (ʏ 0x01A蕨̏ꍇ̂ݕύX)
  #--------------------------------------------------------------------------
  def passable?(x, y, flag = 0x01)
    for event in events_xy(x, y)            # WvCxg𒲂ׂ
      next if event.tile_id == 0            # OtBbN^Cł͂Ȃ
      next if event.priority_type > 0       # [ʏL̉] ł͂Ȃ
      next if event.through                 # 蔲
      pass = @passages[event.tile_id]       # ʍs擾
      next if pass & 0x10 == 0x10           # [] : ʍsɉeȂ
      return true if pass & flag == 0x00    # [] : ʍs
      return false if pass & flag == flag   # [~] : ʍss
    end
    for i in [2, 1, 0]                      # C[̏ォ珇ɒׂ
      tile_id = @map.data[x, y, i]          # ^C ID 擾
      return false if tile_id == nil        # ^C ID 擾s : ʍss
      pass = @passages[tile_id]             # ʍs擾
      next if pass & 0x10 == 0x10           # [] : ʍsɉeȂ
      return true if pass & flag == 0x00    # [] : ʍs
      return false if pass & flag == flag   # [~] : ʍss
    end
    return false                            # ʍss
  end
  #--------------------------------------------------------------------------
  #  ^D̒ʍs\
  #     x : X W
  #     y : Y W
  #--------------------------------------------------------------------------
  def boat_passable?(x, y)
    return passable?(x, y, 0x02)
  end
  #--------------------------------------------------------------------------
  #  ^D̒ʍs\
  #     x : X W
  #     y : Y W
  #--------------------------------------------------------------------------
  def ship_passable?(x, y)
    return passable?(x, y, 0x04)
  end
  #--------------------------------------------------------------------------
  #  sD̒\
  #     x : X W
  #     y : Y W
  #--------------------------------------------------------------------------
  def airship_land_ok?(x, y)
    return passable?(x, y, 0x08)
  end
  #--------------------------------------------------------------------------
  #  ΂ݔ
  #     x : X W
  #     y : Y W
  #--------------------------------------------------------------------------
  def bush?(x, y)
    return false unless valid?(x, y)
    return @passages[@map.data[x, y, 1]] & 0x40 == 0x40
  end
  #--------------------------------------------------------------------------
  #  JE^[
  #     x : X W
  #     y : Y W
  #--------------------------------------------------------------------------
  def counter?(x, y)
    return false unless valid?(x, y)
    return @passages[@map.data[x, y, 0]] & 0x80 == 0x80
  end
  #--------------------------------------------------------------------------
  #  XN[̊Jn
  #     direction : XN[
  #     distance  : XN[鋗
  #     speed     : XN[鑬x
  #--------------------------------------------------------------------------
  def start_scroll(direction, distance, speed)
    @scroll_direction = direction
    @scroll_rest = distance * 256
    @scroll_speed = speed
  end
  #--------------------------------------------------------------------------
  #  XN[
  #--------------------------------------------------------------------------
  def scrolling?
    return @scroll_rest > 0
  end
  #--------------------------------------------------------------------------
  #  t[XV
  #--------------------------------------------------------------------------
  def update
    refresh if $game_map.need_refresh
    update_scroll
    update_events
    update_vehicles
    update_parallax
    @screen.update
  end
  #--------------------------------------------------------------------------
  #  XN[̍XV
  #--------------------------------------------------------------------------
  def update_scroll
    if @scroll_rest > 0                 # XN[̏ꍇ
      distance = 2 ** @scroll_speed     # }bvWnł̋ɕϊ
      case @scroll_direction
      when 2  # 
        scroll_down(distance)
      when 4  # 
        scroll_left(distance)
      when 6  # E
        scroll_right(distance)
      when 8  # 
        scroll_up(distance)
      end
      @scroll_rest -= distance          # XN[Z
    end
  end
  #--------------------------------------------------------------------------
  #  Cxg̍XV
  #--------------------------------------------------------------------------
  def update_events
    for event in @events.values
      event.update
    end
    for common_event in @common_events.values
      common_event.update
    end
  end
  #--------------------------------------------------------------------------
  #  蕨̍XV
  #--------------------------------------------------------------------------
  def update_vehicles
    for vehicle in @vehicles
      vehicle.update
    end
  end
  #--------------------------------------------------------------------------
  #  i̍XV
  #--------------------------------------------------------------------------
  def update_parallax
    @parallax_x += @parallax_sx * 4 if @parallax_loop_x
    @parallax_y += @parallax_sy * 4 if @parallax_loop_y
  end
end
