#==============================================================================
# ** Game_CharacterBase
#------------------------------------------------------------------------------
#  This base class handles characters. It retains basic information, such as
# coordinates and graphics, shared by all characters.
#==============================================================================
class Game_CharacterBase
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_reader   :under_map_tile_z                                                               # Under Map Tile Z Flag
  attr_reader   :over_map_tile_z                                                                  # Over Map Tile Z Flag 
  attr_accessor :character_bitmap_area                            # Character Bitmap Area
  #--------------------------------------------------------------------------
  # * Alias Listing & Method Definition
  #-------------------------------------------------------------------------- 
  # Alias Method List
  ["init_private_members", "increase_steps", "moveto", "screen_z"].each {|name|
                # Alias Method
                alias_method :"pvgames_under_map_tile_z_game_characterbase_#{name}", name
                # Next if Methods don't need definition
                next if ["init_private_members", "screen_z"].include?(name)
                # Define Method
                define_method (name.to_sym) {|*args, &block|
                  # Run Original Method
                  self.send "pvgames_under_map_tile_z_game_characterbase_#{name}", *args, &block
                  # Update Under Map Tile Z Flag
                  update_under_map_tile_z
                 }
  }
  #--------------------------------------------------------------------------
  # * Initialize Private Member Variables
  #--------------------------------------------------------------------------
  def init_private_members(*args, &block)
                # Run Original Method
                pvgames_under_map_tile_z_game_characterbase_init_private_members(*args, &block)
                # Set Under/Over Map Tile Z Flag
                @under_map_tile_z = false ; @over_map_tile_z = false
                # Set Character Bitmap Area Rect
                @character_bitmap_area = Rect.new(0, 0, 1, 1)
  end   
  #--------------------------------------------------------------------------
  # * Get Screen Z-Coordinates
  #--------------------------------------------------------------------------
  def screen_z(*args, &block)
                # Return 300 if Under/Over Map Tile Z is true
                return 300 if under_map_tile_z? or over_map_tile_z?
                # Run Original Method
                pvgames_under_map_tile_z_game_characterbase_screen_z(*args, &block)
  end
  #--------------------------------------------------------------------------
  # * Opacity
  #--------------------------------------------------------------------------
  def opacity
                return @opacity if over_map_tile_z?
                return under_map_tile_z? ? 160 : @opacity
  end
  #--------------------------------------------------------------------------
  # * Determine if Under Map Tile Z effect is true
  #--------------------------------------------------------------------------
  def under_map_tile_z? ; @under_map_tile_z end
  def over_map_tile_z?  ; (!under_map_tile_z? and @over_map_tile_z) end   
  #--------------------------------------------------------------------------
  # * Update Under Map Tile Z Flag
  #--------------------------------------------------------------------------
  def update_under_map_tile_z
                # Get Character Area Bitmap Rect
                rect = @character_bitmap_area.dup
                # If Rect Width or Height is More than 32
                if rect.width >= 32 or rect.height > 32
                  # Set Rect Width and Height
                  rect.width = (rect.width / 32.0).round ; rect.height = (rect.height / 32.0).round
                  # Set Rect X & Y
                  rect.x = @x - (rect.width / 2) ; rect.y = @y - ( rect.height / 2)
                  # Set Over Map Tile Z to false
                  @over_map_tile_z = false
                  # Multiple Loops Catch
                  catch(:range) {   
                                # Go Through coordinates
                                for y in rect.y...(rect.y + rect.height)
                                  for x in rect.x...(rect.x + rect.width)
                                                # If Under Map Tile
                                                if under_map_tile?(x, y)
                                                  # Set Over Map Tile Z to true
                                                  @over_map_tile_z = true
                                                  # Break Loop
                                                  throw :range
                                                end
                                  end
                                end
                  }
                  # Go Through Bottom X
                  for x in rect.x...(rect.x + rect.width)
                                # Return Under Map Tile Z as true if under map tile
                                return @under_map_tile_z = true if under_map_tile?(x, @y)
                  end   
                end   
                # Set Under Map Tile Z
                @under_map_tile_z = under_map_tile?
  end
  #--------------------------------------------------------------------------
  # * Determine if Character is under tile
  #--------------------------------------------------------------------------
  def under_map_tile?(x = @x, y = @y) ; $game_map.over_character_tile?(x, y) end
end

#==============================================================================
# ** Game_Map
#------------------------------------------------------------------------------
#  This class handles maps. It includes scrolling and passage determination
# functions. The instance of this class is referenced by $game_map.
#==============================================================================


class Game_Map
  #--------------------------------------------------------------------------
  # * Determine if Tile goes over character [☆]
  #--------------------------------------------------------------------------
  def over_character_tile?(x, y)
        # Return if Tile is default for nothing
        return false if tile_id(x, y, 2) == 0
        # Check if Valid tile and bit (Over Character)
        # Instead of checking everything, just check layer 2. Seems like 
        # Layer 1 are automatically assigned for you, which may be bad
        return valid?(x, y) && transparent_tile?(x, y)
  end

  def transparent_tile?(x, y)
        tileset.flags[tile_id(x, y, 2)] & 0x10 != 0
  end
end

#==============================================================================
# ** Sprite_Character
#------------------------------------------------------------------------------
#  This sprite is used to display characters. It observes an instance of the
# Game_Character class and automatically changes sprite state.
#==============================================================================
class Sprite_Character < Sprite_Base
  #--------------------------------------------------------------------------
  # * Alias Listing & Method Definition
  #-------------------------------------------------------------------------- 
  # Alias Method List
  ["set_tile_bitmap", "set_character_bitmap"].each {|name|
                # Alias Method
                alias_method :"pvgames_under_map_tile_z_sprite_character_#{name}", name
                # Define Method
                define_method (name.to_sym) {|*args, &block|
                  # Run Original Method
                  self.send "pvgames_under_map_tile_z_sprite_character_#{name}", *args, &block
                  # Update Character Bitmap Area
                  update_character_bitmap_area
                 }
  }
  #--------------------------------------------------------------------------
  # * Update Character Bitmap Area
  #--------------------------------------------------------------------------
  def update_character_bitmap_area
                # Update Source Rect
                update_src_rect
                # Set Character Bitmap Area Rect
                @character.character_bitmap_area.set(0, 0, width, height)
  end
end


#==============================================================================
# ** Game_Event
#------------------------------------------------------------------------------
#  This class handles events. Functions include event page switching via
# condition determinants and running parallel process events. Used within the
# Game_Map class.
#==============================================================================
class Game_Event < Game_Character
  #--------------------------------------------------------------------------
  # * Alias Listing & Method Definition
  #-------------------------------------------------------------------------- 
  # Alias Method List
  ["refresh", "clear_page_settings", "setup_page_settings"].each {|name|
                # Alias Method
                alias_method :"pvgames_under_map_tile_z_game_event_#{name}", name
                # Define Method
                define_method (name.to_sym) {|*args, &block|
                  # Run Original Method
                  self.send "pvgames_under_map_tile_z_game_event_#{name}", *args, &block
                  # Update Under Map Tile Z Flag
                  update_under_map_tile_z
                 }
  } 
end