#Patch snippit of Following Pokemon EX v2.2.4 by Gardenette
module FollowingPkmn
  def self.can_talk?(interact = false)
    return false if !FollowingPkmn.can_check?
    return false if !$game_temp || $game_temp.in_battle || $game_temp.in_menu
    return false if $PokemonGlobal.using_field_move == true
    facing = pbFacingTile
    if !FollowingPkmn.active? || !$game_map.passable?(facing[1], facing[2], $game_player.direction, $game_player)
      if interact
        $game_player.straighten
        EventHandlers.trigger(:on_player_interact)
      end
      return false
    end
    return true
  end
  #edited by Gardenette to prevent followers from popping out on impassible tiles
  def self.toggle(forced = nil, anim = nil)
    return if !FollowingPkmn.can_check? || !FollowingPkmn.get
    return if !FollowingPkmn.get_pokemon
    anim_1 = FollowingPkmn.active?
    if !forced.nil?
      # This may seem redundant but it keeps follower_toggled a boolean always
      $PokemonGlobal.follower_toggled = !(!forced)
    else
      $PokemonGlobal.follower_toggled = !($PokemonGlobal.follower_toggled)
    end
    
    #added by Gardenette
    Game_FollowingPkmn.justCameOut if $PokemonGlobal.follower_toggled == true
    
    anim_2 = FollowingPkmn.active?
    anim = anim_1 != anim_2 if anim.nil?
    FollowingPkmn.refresh(anim)
    $game_temp.followers.move_followers
    $game_temp.followers.turn_followers
  end
end
class Game_FollowingPkmn < Game_Follower
 
  #added by Gardenette
  def self.justCameOut
    @@justCameOut = true
  end
 
  #added by Gardenette
  def tileWaterOrWaterfall?(x, y)
    @map = $game_map
    tileset = $data_tilesets[@map.tileset_id]
    @terrain_tags    = tileset.terrain_tags
    
    #if the target tile is water and the pokemon cannot come out on water
    [2, 1, 0].each do |i|
      tile_id = $game_map.data[x, y, i]
      next if tile_id == 0
      terrain = GameData::TerrainTag.try_get(@terrain_tags[tile_id])
      if terrain
        if terrain.can_surf || terrain.waterfall
          return true
        else
          return false
        end    #if terrain.can_surf || terrain.waterfall
      end #if terrain
    end #[2, 1, 0].each do |i|
  end #def tileWaterOrWaterfall?(x, y)
 
  def followerCanStepOnWater?
    #if the pokemon is water or a flying follower
    pkmn = FollowingPkmn.get_pokemon
    return false if FollowingPkmn::SURFING_FOLLOWERS_EXCEPTIONS.any? do |s|
                    s == pkmn.species || s.to_s == "#{pkmn.species}_#{pkmn.form}"
                  end
    return true if FollowingPkmn.airborne_follower?
    return true if pkmn.hasType?(:WATER)
  end
 
  #edited by Gardenette to prevent followers from popping up on impassible objects
  def follow_leader(leader, instant = false, leaderIsTrueLeader = true)
    maps_connected = $map_factory.areConnected?(leader.map.map_id, self.map.map_id)
    target = nil
    
    if !defined?(@@justCameOut)
      @@justCameOut = false
    end
    
    # Get the target tile that self wants to move to
    if maps_connected
      behind_direction = 10 - leader.direction
      target = $map_factory.getFacingTile(behind_direction, leader)
      
      if target && $map_factory.getTerrainTag(target[0], target[1], target[2]).ledge
        # Get the tile above the ledge (where the leader jumped from)
        target = $map_factory.getFacingTileFromPos(target[0], target[1], target[2], behind_direction)
      end
      target = [leader.map.map_id, leader.x, leader.y] if !target
      if GameData::TerrainTag.exists?(:StairLeft)
        currentTag = $map_factory.getTerrainTag(self.map.map_id, self.x, self.y)
        if currentTag == :StairLeft
          target[2] += (target[1] > $game_player.x ? -1 : 1)
        elsif currentTag == :StairRight
          target[2] += (target[1] < $game_player.x ? -1 : 1)
        end
      end
      # Added
      if defined?(on_stair?) && on_stair?
        if leader.on_stair?
          if leader.stair_start_x != self.stair_start_x
            # Leader stepped on other side so start/end swapped, but not for follower yet
            target[2] = self.y
          elsif leader.stair_start_x < leader.stair_end_x
            # Left to Right
            if leader.x < leader.stair_start_x && self.x != self.stair_start_x
              # Leader stepped off
              target[2] = self.y
            end
          elsif leader.stair_end_x < leader.stair_start_x
            # Right to Left
            if leader.x > leader.stair_start_x && self.x != self.stair_start_x
              # Leader stepped off
              target[2] = self.y
            end
          end
        elsif self.on_middle_of_stair?
          # Leader is no longer on stair but follower is, so player moved up or down at the start or end of the stair
          if leader.y < self.stair_end_y - self.stair_y_height + 1 || leader.y > self.stair_end_y
            target[2] = self.y
          end
        end
      end
    else
      # Map transfer to an unconnected map
      target = [leader.map.map_id, leader.x, leader.y]
    end
    
    if @@justCameOut == true
        if !location_passable?(target[1],target[2], behind_direction) || tileWaterOrWaterfall?(target[1],target[2])
            i = 1
            4.times do
            #2=down, 4=left, 6=right, 8=up
            #behind_direction = 10 - leader.direction
            target = $map_factory.getFacingTile(i*2, leader)
          
            #def location_passable?(x, y, direction)
            if location_passable?(target[1],target[2], behind_direction) && !tileWaterOrWaterfall?(target[1],target[2])
                #if the direction is passable, don't bother checking other directions
                break
            end
            i += 1
          end #4.times do
        
            if !location_passable?(target[1],target[2], behind_direction) || tileWaterOrWaterfall?(target[1],target[2])
                #if the pokemon is water or a flying follower
                if followerCanStepOnWater?
                  #can pop out on the water
                else
                  @@justCameOut = false
                  FollowingPkmn.toggle
                end
            end
        end #if !passable?
        @@justCameOut = false
    end #if @@justCameOut == true
    
    # Move self to the target
    if self.map.map_id != target[0]
      vector = $map_factory.getRelativePos(target[0], 0, 0, self.map.map_id, @x, @y)
      @map = $map_factory.getMap(target[0])
      # NOTE: Can't use moveto because vector is outside the boundaries of the
      #       map, and moveto doesn't allow setting invalid coordinates.
      @x = vector[0]
      @y = vector[1]
      @real_x = @x * Game_Map::REAL_RES_X
      @real_y = @y * Game_Map::REAL_RES_Y
    end
    if instant || !maps_connected
      moveto(target[1], target[2])
    else
      fancy_moveto(target[1], target[2], leader)
    end
  end
  #-----------------------------------------------------------------------------
end
class PokemonGlobalMetadata
  # Added to see if a pokemon is using a field move
  attr_accessor :using_field_move
end
#added here by Gardenette from Game_Map
def playerPassable?(x, y, d, self_event = nil)
    map = $game_map
    tileset = $data_tilesets[map.tileset_id]
    terrain_tags    = tileset.terrain_tags
    passages        = tileset.passages
    priorities      = tileset.priorities
    bit = (1 << ((d / 2) - 1)) & 0x0f
    [2, 1, 0].each do |i|
      tile_id = $game_map.data[x, y, i]
      next if tile_id == 0
      terrain = GameData::TerrainTag.try_get(terrain_tags[tile_id])
      passage = passages[tile_id]
      if terrain
        # Ignore bridge tiles if not on a bridge
        next if terrain.bridge && $PokemonGlobal.bridge == 0
        # Make water tiles passable if player is surfing
        return true if $PokemonGlobal.surfing && terrain.can_surf && !terrain.waterfall
        # Prevent cycling in really tall grass/on ice
        return false if $PokemonGlobal.bicycle && terrain.must_walk
        # Depend on passability of bridge tile if on bridge
        if terrain.bridge && $PokemonGlobal.bridge > 0
          return (passage & bit == 0 && passage & 0x0f != 0x0f)
        end
      end
      next if terrain&.ignore_passability
      # Regular passability checks
      return false if passage & bit != 0 || passage & 0x0f == 0x0f
      return true if priorities[tile_id] == 0
    end
    return true
end
 
def pbHiddenMoveAnimation(pokemon, no_field_move = false)
  no_field_move = no_field_move || $game_temp.no_follower_field_move
  ret = __followingpkmn__pbHiddenMoveAnimation(pokemon)
  return ret if !ret || no_field_move || !FollowingPkmn.active? || pokemon != FollowingPkmn.get_pokemon
 
  #added by Gardenette
  $PokemonGlobal.using_field_move = true
 
  pbTurnTowardEvent(FollowingPkmn.get_event, $game_player)
  pbWait(Graphics.frame_rate / 5)
  FollowingPkmn.move_route([PBMoveRoute::Forward])
  initialDir = $game_player.direction
  movedDir = 0
  case $game_player.direction
  when 2
  #player is facing down
    #try going up
    if playerPassable?($game_player.x, $game_player.y-1, 8) && movedDir <= 0
        pbMoveRoute($game_player, [PBMoveRoute::Up], true)
        movedDir = 8
        pbMoveRoute($game_player, [PBMoveRoute::TurnDown], true)
    end
    #try going left
    if playerPassable?($game_player.x-1, $game_player.y, 4) && movedDir <= 0
        pbMoveRoute($game_player, [PBMoveRoute::Left], true)
        movedDir = 4
        pbMoveRoute($game_player, [PBMoveRoute::TurnRight], true)
    end
    #try going right
    if playerPassable?($game_player.x+1, $game_player.y, 6) && movedDir <= 0
        pbMoveRoute($game_player, [PBMoveRoute::Right], true)
        movedDir = 6
        pbMoveRoute($game_player, [PBMoveRoute::TurnLeft], true)
    end
  when 4
  #player is facing left
    #try going right
    if playerPassable?($game_player.x+1, $game_player.y, 6) && movedDir <= 0
        pbMoveRoute($game_player, [PBMoveRoute::Right], true)
        movedDir = 6
        pbMoveRoute($game_player, [PBMoveRoute::TurnLeft], true)
    end
    #try going down
    if playerPassable?($game_player.x, $game_player.y+1, 2) && movedDir <= 0
        pbMoveRoute($game_player, [PBMoveRoute::Down], true)
        movedDir = 2
        pbMoveRoute($game_player, [PBMoveRoute::TurnUp], true)
    end
    #try going up
    if playerPassable?($game_player.x, $game_player.y-1, 8) && movedDir <= 0
        pbMoveRoute($game_player, [PBMoveRoute::Up], true)
        movedDir = 8
        pbMoveRoute($game_player, [PBMoveRoute::TurnDown], true)
    end
  when 6
  #player is facing right
    #try going left
    if playerPassable?($game_player.x-1, $game_player.y, 4) && movedDir <= 0
        pbMoveRoute($game_player, [PBMoveRoute::Left], true)
        movedDir = 4
        pbMoveRoute($game_player, [PBMoveRoute::TurnRight], true)
    end
    #try going down
    if playerPassable?($game_player.x, $game_player.y+1, 2) && movedDir <= 0
        pbMoveRoute($game_player, [PBMoveRoute::Down], true)
        movedDir = 2
        pbMoveRoute($game_player, [PBMoveRoute::TurnUp], true)
    end
    #try going right
    if playerPassable?($game_player.x+1, $game_player.y, 6) && movedDir <= 0
        pbMoveRoute($game_player, [PBMoveRoute::Right], true)
        movedDir = 6
        pbMoveRoute($game_player, [PBMoveRoute::TurnLeft], true)
    end
    #try going up
    if playerPassable?($game_player.x, $game_player.y-1, 8) && movedDir <= 0
        pbMoveRoute($game_player, [PBMoveRoute::Up], true)
        movedDir = 8
        pbMoveRoute($game_player, [PBMoveRoute::TurnDown], true)
    end
  when 8
  #player is facing up
    #try going down
    if playerPassable?($game_player.x, $game_player.y+1, 2) && movedDir <= 0
        pbMoveRoute($game_player, [PBMoveRoute::Down], true)
        movedDir = 2
        pbMoveRoute($game_player, [PBMoveRoute::TurnUp], true)
    end
    #try going left
    if playerPassable?($game_player.x-1, $game_player.y, 4) && movedDir <= 0
        pbMoveRoute($game_player, [PBMoveRoute::Left], true)
        movedDir = 4
        pbMoveRoute($game_player, [PBMoveRoute::TurnRight], true)
    end
    #try going right
    if playerPassable?($game_player.x+1, $game_player.y, 6) && movedDir <= 0
        pbMoveRoute($game_player, [PBMoveRoute::Right], true)
        movedDir = 6
        pbMoveRoute($game_player, [PBMoveRoute::TurnLeft], true)
    end
    
  end #case $game_player.direction
 
  pbWait(Graphics.frame_rate / 5)
  pbTurnTowardEvent($game_player, FollowingPkmn.get_event)
  pbWait(Graphics.frame_rate / 5)
 
  case initialDir
  when 2
    #player's initial direction was down
    FollowingPkmn.move_route([PBMoveRoute::TurnDown])
  when 4
    #player's initial direction was left
    FollowingPkmn.move_route([PBMoveRoute::TurnLeft])
  when 6
    #player's initial direction was right
    FollowingPkmn.move_route([PBMoveRoute::TurnRight])
  when 8
    #player's initial direction was up
    FollowingPkmn.move_route([PBMoveRoute::TurnUp])
  end
  pbWait(Graphics.frame_rate / 5)
  case movedDir
  when 2
    #player moved down
    pbMoveRoute($game_player, [PBMoveRoute::TurnUp], true)
  when 4
    #player moved left
    pbMoveRoute($game_player, [PBMoveRoute::TurnRight], true)
  when 6
    #player moved right
    pbMoveRoute($game_player, [PBMoveRoute::TurnLeft], true)
  when 8
    #player moved up
    pbMoveRoute($game_player, [PBMoveRoute::TurnDown], true)
  end
  pbSEPlay("Player jump")
  FollowingPkmn.move_route([PBMoveRoute::Jump, 0, 0])
  pbWait(Graphics.frame_rate / 5)
 
  #added by Gardenette
  $PokemonGlobal.using_field_move = false
 
  return ret
end