예제 #1
0
        public static async Task Execute(ISession session, FortData currentFortData, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            if (!session.LogicSettings.CatchWildPokemon)
            {
                return;
            }
            if (session.Runtime.PokeBallsToCollect > 0)
            {
                return;
            }

            if (!await CheckBotStateTask.Execute(session, cancellationToken))
            {
                return;
            }

            // Refresh inventory so that the player stats are fresh
            await session.Inventory.RefreshCachedInventory();

            session.EventDispatcher.Send(new DebugEvent()
            {
                Message = session.Translation.GetTranslation(TranslationString.LookingForLurePokemon)
            });

            var fortId = currentFortData.Id;

            if (currentFortData.LureInfo == null)
            {
                return;
            }

            var pokemonId = currentFortData.LureInfo.ActivePokemonId;

            if (session.LogicSettings.UsePokemonToNotCatchFilter &&
                session.LogicSettings.PokemonsNotToCatch.Contains(pokemonId))
            {
                session.EventDispatcher.Send(new NoticeEvent
                {
                    Message = session.Translation.GetTranslation(TranslationString.PokemonSkipped, session.Translation.GetPokemonName(pokemonId))
                });
            }
            else
            {
                var encounterId = currentFortData.LureInfo.EncounterId;
                var encounter   = await session.Client.Encounter.EncounterLurePokemon(encounterId, fortId);

                if (encounter.Result == DiskEncounterResponse.Types.Result.Success)
                {
                    //var pokemons = await session.MapCache.MapPokemons(session);
                    //var pokemon = pokemons.FirstOrDefault(i => i.PokemonId == encounter.PokemonData.PokemonId);
                    session.EventDispatcher.Send(new DebugEvent()
                    {
                        Message = "Found a Lure Pokemon."
                    });

                    MapPokemon _pokemon = new MapPokemon
                    {
                        EncounterId           = currentFortData.LureInfo.EncounterId,
                        ExpirationTimestampMs = currentFortData.LureInfo.LureExpiresTimestampMs,
                        Latitude     = currentFortData.Latitude,
                        Longitude    = currentFortData.Longitude,
                        PokemonId    = currentFortData.LureInfo.ActivePokemonId,
                        SpawnPointId = currentFortData.LureInfo.FortId
                    };
                    if (session.LogicSettings.UsePokemonToNotCatchFilter &&
                        session.LogicSettings.PokemonsNotToCatch.Contains(_pokemon.PokemonId))
                    {
                        session.EventDispatcher.Send(new NoticeEvent()
                        {
                            Message = session.Translation.GetTranslation(TranslationString.PokemonIgnoreFilter, session.Translation.GetPokemonName(_pokemon.PokemonId))
                        });
                    }
                    else
                    {
                        session.EventDispatcher.Send(new PokemonsFoundEvent {
                            Pokemons = new[] { _pokemon }
                        });
                        PokemonCacheItem pokemon = new PokemonCacheItem(_pokemon);

                        var catchRes = await CatchPokemonTask.Execute(session, encounter, pokemon, cancellationToken, currentFortData, encounterId);

                        if (!catchRes)
                        {
                            session.Runtime.PokeBallsToCollect = 10;
                            return;
                        }
                        currentFortData.LureInfo = null;
                        session.EventDispatcher.Send(new PokemonDisappearEvent {
                            Pokemon = _pokemon
                        });
                    }

                    //await CatchPokemonTask.Execute(session, encounter, pokemon, currentFortData, encounterId);
                }
                else if (encounter.Result == DiskEncounterResponse.Types.Result.PokemonInventoryFull)
                {
                    if (session.LogicSettings.TransferDuplicatePokemon)
                    {
                        session.EventDispatcher.Send(new WarnEvent
                        {
                            Message = session.Translation.GetTranslation(TranslationString.InvFullTransferring)
                        });
                        await TransferDuplicatePokemonTask.Execute(session, cancellationToken);
                    }
                    else
                    {
                        session.EventDispatcher.Send(new WarnEvent
                        {
                            Message = session.Translation.GetTranslation(TranslationString.InvFullTransferManually)
                        });
                    }
                }
                else
                {
                    if (encounter.Result.ToString().Contains("NotAvailable"))
                    {
                        return;
                    }
                    session.EventDispatcher.Send(new WarnEvent
                    {
                        Message =
                            session.Translation.GetTranslation(TranslationString.EncounterProblemLurePokemon,
                                                               encounter.Result)
                    });
                }
                // always wait the delay amount between catches, ideally to prevent you from making another call too early after a catch event
                await Task.Delay(session.LogicSettings.DelayBetweenPokemonCatch);
            }
        }
        public static async Task Execute(ISession session, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            if (!session.LogicSettings.CatchWildPokemon)
            {
                return;
            }
            if (session.Runtime.PokeBallsToCollect > 0)
            {
                return;
            }

            var usedItems = await session.Inventory.GetUsedItems();

            if (usedItems == null || !usedItems.Any(x => x.ItemId == ItemId.ItemIncenseOrdinary || x.ItemId == ItemId.ItemIncenseSpicy ||
                                                    x.ItemId == ItemId.ItemIncenseCool || x.ItemId == ItemId.ItemIncenseFloral))
            {
                return;
            }

            // Refresh inventory so that the player stats are fresh
            //await session.Inventory.RefreshCachedInventory();

            session.EventDispatcher.Send(new DebugEvent
            {
                Message = session.Translation.GetTranslation(TranslationString.LookingForIncensePokemon)
            });

            var incensePokemon = await session.Client.Map.GetIncensePokemons();

            if (incensePokemon.Result == GetIncensePokemonResponse.Types.Result.IncenseEncounterAvailable)
            {
                if (session.LogicSettings.UsePokemonToNotCatchFilter &&
                    session.LogicSettings.PokemonsNotToCatch.Contains(incensePokemon.PokemonId))
                {
                    //session.EventDispatcher.Send(new NoticeEvent
                    //{
                    //    Message = session.Translation.GetTranslation(TranslationString.PokemonIgnoreFilter, session.Translation.GetPokemonName(pokemon.PokemonId))
                    //});
                }
                else
                {
                    var mapPokemon = new MapPokemon
                    {
                        EncounterId           = incensePokemon.EncounterId,
                        ExpirationTimestampMs = incensePokemon.DisappearTimestampMs,
                        Latitude     = incensePokemon.Latitude,
                        Longitude    = incensePokemon.Longitude,
                        PokemonId    = incensePokemon.PokemonId,
                        SpawnPointId = incensePokemon.EncounterLocation
                    };
                    var pokemon = new PokemonCacheItem(mapPokemon);

                    session.EventDispatcher.Send(new PokemonsFoundEvent {
                        Pokemons = new[] { mapPokemon }
                    });

                    await Task.Delay(session.LogicSettings.DelayCatchIncensePokemon, cancellationToken);

                    var encounter =
                        await
                        session.Client.Encounter.EncounterIncensePokemon(pokemon.EncounterId,
                                                                         pokemon.SpawnPointId);

                    if (encounter.Result == IncenseEncounterResponse.Types.Result.IncenseEncounterSuccess)
                    {
                        var catchRes = await CatchPokemonTask.Execute(session, encounter, pokemon, cancellationToken);

                        if (!catchRes)
                        {
                            session.Runtime.PokeBallsToCollect = 10;
                            return;
                        }
                    }
                    else if (encounter.Result == IncenseEncounterResponse.Types.Result.PokemonInventoryFull)
                    {
                        if (session.LogicSettings.TransferDuplicatePokemon)
                        {
                            session.EventDispatcher.Send(new WarnEvent
                            {
                                Message = session.Translation.GetTranslation(TranslationString.InvFullTransferring)
                            });
                            await TransferDuplicatePokemonTask.Execute(session, cancellationToken);
                        }
                        else
                        {
                            session.EventDispatcher.Send(new WarnEvent
                            {
                                Message = session.Translation.GetTranslation(TranslationString.InvFullTransferManually)
                            });
                        }
                    }
                    else
                    {
                        session.EventDispatcher.Send(new WarnEvent
                        {
                            Message =
                                session.Translation.GetTranslation(TranslationString.EncounterProblem, encounter.Result)
                        });
                    }
                    session.EventDispatcher.Send(new PokemonDisappearEvent {
                        EncounterId = pokemon.EncounterId
                    });
                }
            }
        }
예제 #3
0
        public static async Task  Execute(ISession session, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            //Refresh inventory so that the player stats are fresh
            //await session.Inventory.RefreshCachedInventory(); too much inventore refresh

            session.EventDispatcher.Send(new DebugEvent()
            {
                Message = session.Translation.GetTranslation(TranslationString.LookingForPokemon)
            });

            var pokemons = await GetNearbyPokemons(session);

            if (session.LogicSettings.UsePokemonToNotCatchFilter)
            {
                var pokeToCatch =
                    pokemons.Select(x => x.BaseMapPokemon)
                    .Where(x => !session.LogicSettings.PokemonsNotToCatch.Contains(x.PokemonId));
                session.EventDispatcher.Send(new PokemonsFoundEvent {
                    Pokemons = pokeToCatch
                });
            }
            else
            {
                session.EventDispatcher.Send(new PokemonsFoundEvent {
                    Pokemons = pokemons.Select(x => x.BaseMapPokemon)
                });
            }
            foreach (var pokemon in pokemons)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var pokeBallsCount = await session.Inventory.GetItemAmountByType(ItemId.ItemPokeBall);

                var greatBallsCount = await session.Inventory.GetItemAmountByType(ItemId.ItemGreatBall);

                var ultraBallsCount = await session.Inventory.GetItemAmountByType(ItemId.ItemUltraBall);

                var masterBallsCount = await session.Inventory.GetItemAmountByType(ItemId.ItemMasterBall);

                if (pokeBallsCount + greatBallsCount + ultraBallsCount + masterBallsCount == 0)
                {
                    session.EventDispatcher.Send(new NoticeEvent()
                    {
                        Message = session.Translation.GetTranslation(TranslationString.ZeroPokeballInv)
                    });
                    return;
                }

                if (session.LogicSettings.UsePokemonToNotCatchFilter &&
                    session.LogicSettings.PokemonsNotToCatch.Contains(pokemon.PokemonId))
                {
                    session.EventDispatcher.Send(new NoticeEvent()
                    {
                        Message =
                            session.Translation.GetTranslation(TranslationString.PokemonSkipped,
                                                               session.Translation.GetPokemonName(pokemon.PokemonId))
                    });
                    continue;
                }

                var distance = LocationUtils.CalculateDistanceInMeters(session.Client.CurrentLatitude,
                                                                       session.Client.CurrentLongitude, pokemon.Latitude, pokemon.Longitude);
                await Task.Delay(distance > 100? 3000 : 500, cancellationToken);

                var encounter =
                    await session.Client.Encounter.EncounterPokemon(pokemon.EncounterId, pokemon.SpawnPointId);

                try
                {
                    switch (encounter.Status)
                    {
                    case EncounterResponse.Types.Status.EncounterSuccess:
                        await CatchPokemonTask.Execute(session, encounter, pokemon);

                        break;

                    case EncounterResponse.Types.Status.PokemonInventoryFull:
                        if (session.LogicSettings.TransferDuplicatePokemon)
                        {
                            session.EventDispatcher.Send(new WarnEvent
                            {
                                Message = session.Translation.GetTranslation(TranslationString.InvFullTransferring)
                            });
                            await TransferDuplicatePokemonTask.Execute(session, cancellationToken);
                        }
                        else
                        {
                            session.EventDispatcher.Send(new WarnEvent
                            {
                                Message =
                                    session.Translation.GetTranslation(TranslationString.InvFullTransferManually)
                            });
                        }
                        break;

                    default:
                        session.EventDispatcher.Send(new WarnEvent
                        {
                            Message =
                                session.Translation.GetTranslation(TranslationString.EncounterProblem,
                                                                   encounter.Status)
                        });
                        break;
                    }
                }
                catch (Exception)
                {
                    session.EventDispatcher.Send(new WarnEvent
                    {
                        Message = "Error occured while trying to catch nearby pokemon"
                    });
                    await Task.Delay(5000, cancellationToken);
                }

                session.EventDispatcher.Send(new PokemonDisappearEvent {
                    Pokemon = pokemon.BaseMapPokemon
                });

                // always wait the delay amount between catches, ideally to prevent you from making another call too early after a catch event
                await Task.Delay(session.LogicSettings.DelayBetweenPokemonCatch);
            }
            return;
        }
예제 #4
0
        public static async Task Execute(ISession session, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // Refresh inventory so that the player stats are fresh
            await session.Inventory.RefreshCachedInventory();

            session.EventDispatcher.Send(new DebugEvent()
            {
                Message = session.Translation.GetTranslation(TranslationString.LookingForIncensePokemon)
            });

            var incensePokemon = await session.Client.Map.GetIncensePokemons();

            if (incensePokemon.Result == GetIncensePokemonResponse.Types.Result.IncenseEncounterAvailable)
            {
                var _pokemon = new MapPokemon
                {
                    EncounterId           = incensePokemon.EncounterId,
                    ExpirationTimestampMs = incensePokemon.DisappearTimestampMs,
                    Latitude     = incensePokemon.Latitude,
                    Longitude    = incensePokemon.Longitude,
                    PokemonId    = incensePokemon.PokemonId,
                    SpawnPointId = incensePokemon.EncounterLocation
                };
                var pokemon = new PokemonCacheItem(_pokemon);

                session.EventDispatcher.Send(new PokemonsFoundEvent {
                    Pokemons = new MapPokemon[] { _pokemon }
                });

                if (session.LogicSettings.UsePokemonToNotCatchFilter &&
                    session.LogicSettings.PokemonsNotToCatch.Contains(pokemon.PokemonId))
                {
                    session.EventDispatcher.Send(new NoticeEvent()
                    {
                        Message = session.Translation.GetTranslation(TranslationString.PokemonIgnoreFilter, session.Translation.GetPokemonName(pokemon.PokemonId))
                    });
                }
                else
                {
                    var distance = LocationUtils.CalculateDistanceInMeters(session.Client.CurrentLatitude,
                                                                           session.Client.CurrentLongitude, pokemon.Latitude, pokemon.Longitude);
                    await Task.Delay(session.LogicSettings.DelayCatchIncensePokemon);

                    var encounter =
                        await
                        session.Client.Encounter.EncounterIncensePokemon(pokemon.EncounterId,
                                                                         pokemon.SpawnPointId);

                    if (encounter.Result == IncenseEncounterResponse.Types.Result.IncenseEncounterSuccess)
                    {
                        await CatchPokemonTask.Execute(session, encounter, pokemon);
                    }
                    else if (encounter.Result == IncenseEncounterResponse.Types.Result.PokemonInventoryFull)
                    {
                        if (session.LogicSettings.TransferDuplicatePokemon)
                        {
                            session.EventDispatcher.Send(new WarnEvent
                            {
                                Message = session.Translation.GetTranslation(TranslationString.InvFullTransferring)
                            });
                            await TransferDuplicatePokemonTask.Execute(session, cancellationToken);
                        }
                        else
                        {
                            session.EventDispatcher.Send(new WarnEvent
                            {
                                Message = session.Translation.GetTranslation(TranslationString.InvFullTransferManually)
                            });
                        }
                    }
                    else
                    {
                        session.EventDispatcher.Send(new WarnEvent
                        {
                            Message =
                                session.Translation.GetTranslation(TranslationString.EncounterProblem, encounter.Result)
                        });
                    }
                }
                session.EventDispatcher.Send(new PokemonDisappearEvent {
                    Pokemon = pokemon.BaseMapPokemon
                });
            }
        }
예제 #5
0
        private static async Task <bool> Snipe(ISession session, IEnumerable <PokemonId> pokemonIds, double Latitude,
                                               double Longitude, CancellationToken cancellationToken)
        {
            var CurrentLatitude  = session.Client.CurrentLatitude;
            var CurrentLongitude = session.Client.CurrentLongitude;

            session.EventDispatcher.Send(new SnipeModeEvent {
                Active = true
            });

            await
            session.Client.Player.UpdatePlayerLocation(Latitude,
                                                       Longitude, session.Client.CurrentAltitude);

            session.EventDispatcher.Send(new UpdatePositionEvent
            {
                Longitude = Longitude,
                Latitude  = Latitude
            });

            var mapObjects       = session.Client.Map.GetMapObjects().Result;
            var catchablePokemon =
                mapObjects.MapCells.SelectMany(q => q.CatchablePokemons)
                .Where(q => pokemonIds.Contains(q.PokemonId))
                .ToList();

            await session.Client.Player.UpdatePlayerLocation(CurrentLatitude, CurrentLongitude,
                                                             session.Client.CurrentAltitude);

            foreach (var pokemon in catchablePokemon)
            {
                //var pokemon = new PokemonCacheItem(_pokemon);
                cancellationToken.ThrowIfCancellationRequested();

                EncounterResponse encounter;
                try
                {
                    await
                    session.Client.Player.UpdatePlayerLocation(Latitude, Longitude, session.Client.CurrentAltitude);

                    encounter =
                        session.Client.Encounter.EncounterPokemon(pokemon.EncounterId, pokemon.SpawnPointId).Result;
                }
                finally
                {
                    await
                    session.Client.Player.UpdatePlayerLocation(CurrentLatitude, CurrentLongitude, session.Client.CurrentAltitude);
                }

                if (encounter.Status == EncounterResponse.Types.Status.EncounterSuccess)
                {
                    session.EventDispatcher.Send(new UpdatePositionEvent
                    {
                        Latitude  = CurrentLatitude,
                        Longitude = CurrentLongitude
                    });

                    if (!await CatchPokemonTask.Execute(session, encounter, new PokemonCacheItem(pokemon)))
                    {
                        // Don't snipe any more pokemon if we ran out of one kind of pokeballs.
                        session.EventDispatcher.Send(new SnipeModeEvent {
                            Active = false
                        });
                        return(false);
                    }
                }
                else if (encounter.Status == EncounterResponse.Types.Status.PokemonInventoryFull)
                {
                    session.EventDispatcher.Send(new WarnEvent
                    {
                        Message =
                            session.Translation.GetTranslation(
                                TranslationString.InvFullTransferManually)
                    });

                    // Don't snipe any more pokemon if inventory is full.
                    session.EventDispatcher.Send(new SnipeModeEvent {
                        Active = false
                    });
                    return(false);
                }
                else
                {
                    session.EventDispatcher.Send(new WarnEvent
                    {
                        Message =
                            session.Translation.GetTranslation(
                                TranslationString.EncounterProblem, encounter.Status)
                    });
                }

                if (
                    !Equals(catchablePokemon.ElementAtOrDefault(catchablePokemon.Count - 1),
                            pokemon))
                {
                    await Task.Delay(session.LogicSettings.DelayBetweenPokemonCatch, cancellationToken);
                }
            }

            session.EventDispatcher.Send(new SnipeModeEvent {
                Active = false
            });
            await Task.Delay(session.LogicSettings.DelayBetweenPlayerActions, cancellationToken);

            return(true);
        }
예제 #6
0
        public static async Task Execute(ISession session, FortData currentFortData, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // Refresh inventory so that the player stats are fresh
            await session.Inventory.RefreshCachedInventory();

            session.EventDispatcher.Send(new DebugEvent()
            {
                Message = session.Translation.GetTranslation(TranslationString.LookingForLurePokemon)
            });

            var fortId = currentFortData.Id;

            var pokemonId = currentFortData.LureInfo.ActivePokemonId;

            if (session.LogicSettings.UsePokemonToNotCatchFilter &&
                session.LogicSettings.PokemonsNotToCatch.Contains(pokemonId))
            {
                session.EventDispatcher.Send(new NoticeEvent
                {
                    Message = session.Translation.GetTranslation(TranslationString.PokemonSkipped, session.Translation.GetPokemonName(pokemonId))
                });
            }
            else
            {
                var encounterId = currentFortData.LureInfo.EncounterId;
                var encounter   = await session.Client.Encounter.EncounterLurePokemon(encounterId, fortId);

                var pokemon = new MapPokemon
                {
                    EncounterId = encounterId,
                    Latitude    = currentFortData.Latitude,
                    Longitude   = currentFortData.Longitude,
                    PokemonId   = pokemonId
                };
                session.EventDispatcher.Send(new PokemonsFoundEvent {
                    Pokemons = new MapPokemon[] { pokemon }
                });

                if (encounter.Result == DiskEncounterResponse.Types.Result.Success)
                {
                    await CatchPokemonTask.Execute(session, encounter, null, currentFortData, encounterId);
                }
                else if (encounter.Result == DiskEncounterResponse.Types.Result.PokemonInventoryFull)
                {
                    if (session.LogicSettings.TransferDuplicatePokemon)
                    {
                        session.EventDispatcher.Send(new WarnEvent
                        {
                            Message = session.Translation.GetTranslation(TranslationString.InvFullTransferring)
                        });
                        await TransferDuplicatePokemonTask.Execute(session, cancellationToken);
                    }
                    else
                    {
                        session.EventDispatcher.Send(new WarnEvent
                        {
                            Message = session.Translation.GetTranslation(TranslationString.InvFullTransferManually)
                        });
                    }
                }
                else
                {
                    if (encounter.Result.ToString().Contains("NotAvailable"))
                    {
                        session.EventDispatcher.Send(new PokemonDisappearEvent {
                            Pokemon = pokemon
                        });
                        return;
                    }
                    session.EventDispatcher.Send(new WarnEvent
                    {
                        Message =
                            session.Translation.GetTranslation(TranslationString.EncounterProblemLurePokemon,
                                                               encounter.Result)
                    });
                }
                session.EventDispatcher.Send(new PokemonDisappearEvent {
                    Pokemon = pokemon
                });
            }
        }
예제 #7
0
        public static async Task Execute(ISession session, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // Refresh inventory so that the player stats are fresh
            await session.Inventory.RefreshCachedInventory();

            session.EventDispatcher.Send(new DebugEvent()
            {
                Message = session.Translation.GetTranslation(TranslationString.LookingForPokemon)
            });

            var pokemons = await GetNearbyPokemons(session);

            foreach (var pokemon in pokemons)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var pokeBallsCount = await session.Inventory.GetItemAmountByType(ItemId.ItemPokeBall);

                var greatBallsCount = await session.Inventory.GetItemAmountByType(ItemId.ItemGreatBall);

                var ultraBallsCount = await session.Inventory.GetItemAmountByType(ItemId.ItemUltraBall);

                var masterBallsCount = await session.Inventory.GetItemAmountByType(ItemId.ItemMasterBall);

                if (pokeBallsCount + greatBallsCount + ultraBallsCount + masterBallsCount == 0)
                {
                    session.EventDispatcher.Send(new NoticeEvent()
                    {
                        Message = session.Translation.GetTranslation(TranslationString.ZeroPokeballInv)
                    });
                    return;
                }

                if (session.LogicSettings.UsePokemonToNotCatchFilter &&
                    session.LogicSettings.PokemonsNotToCatch.Contains(pokemon.PokemonId))
                {
                    session.EventDispatcher.Send(new NoticeEvent()
                    {
                        Message = session.Translation.GetTranslation(TranslationString.PokemonSkipped, session.Translation.GetPokemonName(pokemon.PokemonId))
                    });
                    continue;
                }

                var distance = LocationUtils.CalculateDistanceInMeters(session.Client.CurrentLatitude,
                                                                       session.Client.CurrentLongitude, pokemon.Latitude, pokemon.Longitude);
                await Task.Delay(distance > 100? 3000 : 500, cancellationToken);

                var encounter =
                    await session.Client.Encounter.EncounterPokemon(pokemon.EncounterId, pokemon.SpawnPointId);

                if (encounter.Status == EncounterResponse.Types.Status.EncounterSuccess)
                {
                    await CatchPokemonTask.Execute(session, encounter, pokemon);
                }
                else if (encounter.Status == EncounterResponse.Types.Status.PokemonInventoryFull)
                {
                    if (session.LogicSettings.TransferDuplicatePokemon)
                    {
                        session.EventDispatcher.Send(new WarnEvent
                        {
                            Message = session.Translation.GetTranslation(TranslationString.InvFullTransferring)
                        });
                        await TransferDuplicatePokemonTask.Execute(session, cancellationToken);
                    }
                    else
                    {
                        session.EventDispatcher.Send(new WarnEvent
                        {
                            Message = session.Translation.GetTranslation(TranslationString.InvFullTransferManually)
                        });
                    }
                }
                else
                {
                    session.EventDispatcher.Send(new WarnEvent
                    {
                        Message =
                            session.Translation.GetTranslation(TranslationString.EncounterProblem, encounter.Status)
                    });
                }

                // If pokemon is not last pokemon in list, create delay between catches, else keep moving.
                if (!Equals(pokemons.ElementAtOrDefault(pokemons.Count() - 1), pokemon))
                {
                    if (session.LogicSettings.Teleport)
                    {
                        await Task.Delay(session.LogicSettings.DelayBetweenPokemonCatch);
                    }
                    else
                    {
                        await Task.Delay(session.LogicSettings.DelayBetweenPokemonCatch, cancellationToken);
                    }
                }
            }
        }
        public static async Task  Execute(ISession session, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            //Refresh inventory so that the player stats are fresh
            //await session.Inventory.RefreshCachedInventory(); too much inventory refresh

            await CheckChallengeDoneTask.Execute(session, cancellationToken);

            await CheckChallengeTask.Execute(session, cancellationToken);

            if (!session.LogicSettings.CatchWildPokemon)
            {
                return;
            }

            if (session.Runtime.PokeBallsToCollect > 0)
            {
                return;
            }

            //session.EventDispatcher.Send(new DebugEvent()
            //{
            //    Message = session.Translation.GetTranslation(TranslationString.LookingForPokemon)
            //});

            var pokemons = await GetNearbyPokemons(session);

            if (session.LogicSettings.UsePokemonToNotCatchFilter)
            {
                pokemons = pokemons.Where(x => !session.LogicSettings.PokemonsNotToCatch.Contains(x.PokemonId)).ToList();
            }

            session.EventDispatcher.Send(new PokemonsFoundEvent {
                Pokemons = pokemons.Select(x => x.BaseMapPokemon)
            });
            if (!await CheckBotStateTask.Execute(session, cancellationToken))
            {
                return;
            }

            var prevState = session.State;

            session.State = BotState.FoundPokemons;

            pokemons = pokemons.OrderByDescending(x => x.PokemonId.HowRare()).ToList();

            foreach (var pokemon in pokemons)
            {
                if (pokemon.ExpirationTimestampMs > DateTime.UtcNow.ToUnixTime())
                {
                    continue;
                }

                cancellationToken.ThrowIfCancellationRequested();

                var pokeBallsCount = await session.Inventory.GetItemAmountByType(ItemId.ItemPokeBall);

                var greatBallsCount = await session.Inventory.GetItemAmountByType(ItemId.ItemGreatBall);

                var ultraBallsCount = await session.Inventory.GetItemAmountByType(ItemId.ItemUltraBall);

                var masterBallsCount = await session.Inventory.GetItemAmountByType(ItemId.ItemMasterBall);

                if (pokeBallsCount + greatBallsCount + ultraBallsCount + masterBallsCount == 0)
                {
                    session.EventDispatcher.Send(new NoticeEvent
                    {
                        Message = session.Translation.GetTranslation(TranslationString.ZeroPokeballInv)
                    });
                    session.State = prevState;
                    session.Runtime.PokeBallsToCollect = 10;
                    session.EventDispatcher.Send(new PokemonDisappearEvent {
                        EncounterId = pokemon.EncounterId
                    });
                    continue;
                }

                if (session.LogicSettings.UsePokemonToNotCatchFilter &&
                    session.LogicSettings.PokemonsNotToCatch.Contains(pokemon.PokemonId))
                {
                    if (!pokemon.Caught)
                    {
                        session.EventDispatcher.Send(new NoticeEvent
                        {
                            Message =
                                session.Translation.GetTranslation(TranslationString.PokemonSkipped,
                                                                   session.Translation.GetPokemonName(pokemon.PokemonId))
                        });
                    }
                    pokemon.Caught = true;
                    session.EventDispatcher.Send(new PokemonDisappearEvent {
                        EncounterId = pokemon.EncounterId
                    });
                    continue;
                }

                var distance = LocationUtils.CalculateDistanceInMeters(session.Client.CurrentLatitude,
                                                                       session.Client.CurrentLongitude, pokemon.Latitude, pokemon.Longitude);
                await Task.Delay(distance > 100? 3000 : 500, cancellationToken);

                var encounter =
                    await session.Client.Encounter.EncounterPokemon(pokemon.EncounterId, pokemon.SpawnPointId);

                try
                {
                    switch (encounter.Status)
                    {
                    case EncounterResponse.Types.Status.EncounterSuccess:
                        var catchRes = await CatchPokemonTask.Execute(session, encounter, pokemon, cancellationToken);

                        if (!catchRes)
                        {
                            session.Runtime.PokeBallsToCollect = 10;
                            session.State = prevState;

                            foreach (var p in pokemons)
                            {
                                session.EventDispatcher.Send(new PokemonDisappearEvent {
                                    EncounterId = p.EncounterId
                                });
                            }

                            return;
                        }
                        break;

                    case EncounterResponse.Types.Status.PokemonInventoryFull:
                        if (session.LogicSettings.TransferDuplicatePokemon)
                        {
                            session.EventDispatcher.Send(new WarnEvent
                            {
                                Message = session.Translation.GetTranslation(TranslationString.InvFullTransferring)
                            });
                            session.State = BotState.Idle;
                            await TransferDuplicatePokemonTask.Execute(session, cancellationToken);

                            session.State = BotState.FoundPokemons;
                        }
                        else
                        {
                            session.EventDispatcher.Send(new WarnEvent
                            {
                                Message =
                                    session.Translation.GetTranslation(TranslationString.InvFullTransferManually)
                            });
                        }
                        break;

                    default:
                        session.EventDispatcher.Send(new WarnEvent
                        {
                            Message =
                                session.Translation.GetTranslation(TranslationString.EncounterProblem,
                                                                   encounter.Status)
                        });
                        break;
                    }
                }
                catch (Exception)
                {
                    session.EventDispatcher.Send(new WarnEvent
                    {
                        Message = session.Translation.GetTranslation(TranslationString.ErrorCatchNearby)
                    });
                    await Task.Delay(5000, cancellationToken);
                }

                session.EventDispatcher.Send(new PokemonDisappearEvent {
                    EncounterId = pokemon.EncounterId
                });

                // always wait the delay amount between catches, ideally to prevent you from making another call too early after a catch event
                await Task.Delay(session.LogicSettings.DelayBetweenPokemonCatch, cancellationToken);
            }
            session.State = prevState;
        }