async Task ExecuteCatchCommand() { var encounterPokemonResponse = await Encounter(); if (encounterPokemonResponse.IsSuccess) { MessengerInstance.Send(new Message(Colors.Green, $"Encountered a {encounterPokemonResponse.Pokemon.Name}")); var pokeball = GetPokeBall(); CatchPokemonResponse caughtPokemonResponse = null; do { // returns an exception at the moment. //if (settings.UseRazzBerryWhenPokemonIsAboveCP <= pokemonCP || // settings.UseRazzBerryWhenCatchProbabilityIsBelow <= encounterPokemonResponse.CaptureProbability.CaptureProbability_.First()) // await session.UseCaptureItem(pokemon.EncounterId, POGOProtos.Inventory.Item.ItemId.ItemRazzBerry, pokemon.SpawnPointId); // TODO calculate pokeball based on encountered pokemon if (pokeball.Count > 0) { MessengerInstance.Send(new Message(Colors.Green, $"Using a {pokeball.Name}")); pokeball.Count--; caughtPokemonResponse = await session.CatchPokemon(EncounterId, SpawnPointId, (POGOProtos.Inventory.Item.ItemId) pokeball.ItemType); } else { MessengerInstance.Send(new Message(Colors.Yellow, "No pokeballs left.")); } } while (pokeball.Count > 0 && (caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchMissed || caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape)); if (caughtPokemonResponse != null) { if (caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchSuccess) { encounterPokemonResponse.PokemonData.Id = caughtPokemonResponse.CapturedPokemonId; var caughtPokemon = new CaughtPokemonViewModel(encounterPokemonResponse.PokemonData, session, player.Inventory, settings); var xp = caughtPokemonResponse.CaptureAward.Xp.Sum(); player.Xp += xp; var stardust = caughtPokemonResponse.CaptureAward.Stardust.Sum(); player.Stardust += stardust; var candy = caughtPokemonResponse.CaptureAward.Candy.Sum(); player.Inventory.AddCandyForFamily(candy, caughtPokemon.FamilyId); MessengerInstance.Send(new Message(Colors.Green, $"Caught a {encounterPokemonResponse.Pokemon.Name}. {xp} Xp - {candy} Candy - {stardust} Stardust.")); player.Inventory.Pokemon.AddOrUpdate(caughtPokemon); map.CatchablePokemon.Remove(this); } else if (caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchFlee) { MessengerInstance.Send(new Message(Colors.Red, $"Failed to catch a {encounterPokemonResponse.Pokemon.Name}, because it fled.")); } } } }
/// <summary> /// Because this function sometime being called inside loop, return true it mean we don't want break look, false it mean not need to call this , break a loop from caller function /// </summary> /// <param name="session"></param> /// <param name="cancellationToken"></param> /// <param name="encounter"></param> /// <param name="pokemon"></param> /// <param name="currentFortData"></param> /// <param name="sessionAllowTransfer"></param> /// <returns></returns> public static async Task <bool> Execute(ISession session, CancellationToken cancellationToken, dynamic encounter, MapPokemon pokemon, FortData currentFortData, bool sessionAllowTransfer) { var manager = TinyIoCContainer.Current.Resolve <MultiAccountManager>(); manager.ThrowIfSwitchAccountRequested(); // If the encounter is null nothing will work below, so exit now if (encounter == null) { return(true); } var totalBalls = (await session.Inventory.GetItems().ConfigureAwait(false)).Where(x => x.ItemId == ItemId.ItemPokeBall || x.ItemId == ItemId.ItemGreatBall || x.ItemId == ItemId.ItemUltraBall).Sum(x => x.Count); if (session.SaveBallForByPassCatchFlee && totalBalls < BALL_REQUIRED_TO_BYPASS_CATCHFLEE) { return(false); } // Exit if user defined max limits reached if (session.Stats.CatchThresholdExceeds(session)) { if (manager.AllowMultipleBot() && session.LogicSettings.MultipleBotConfig.SwitchOnCatchLimit && TinyIoCContainer.Current.Resolve <MultiAccountManager>().AllowSwitch()) { throw new ActiveSwitchByRuleException() { MatchedRule = SwitchRules.CatchLimitReached, ReachedValue = session.LogicSettings.CatchPokemonLimit }; } return(false); } using (var block = new BlockableScope(session, BotActions.Catch)) { if (!await block.WaitToRun().ConfigureAwait(false)) { return(true); } AmountOfBerries = new Dictionary <ItemId, int>(); cancellationToken.ThrowIfCancellationRequested(); float probability = encounter.CaptureProbability?.CaptureProbability_[0]; PokemonData encounteredPokemon; long unixTimeStamp; ulong _encounterId; string _spawnPointId; // Calling from CatchNearbyPokemonTask and SnipePokemonTask if (encounter is EncounterResponse && (encounter?.Status == EncounterResponse.Types.Status.EncounterSuccess)) { encounteredPokemon = encounter.WildPokemon?.PokemonData; unixTimeStamp = encounter.WildPokemon?.LastModifiedTimestampMs + encounter.WildPokemon?.TimeTillHiddenMs; _spawnPointId = encounter.WildPokemon?.SpawnPointId; _encounterId = encounter.WildPokemon?.EncounterId; } // Calling from CatchIncensePokemonTask else if (encounter is IncenseEncounterResponse && (encounter?.Result == IncenseEncounterResponse.Types.Result.IncenseEncounterSuccess)) { encounteredPokemon = encounter?.PokemonData; unixTimeStamp = pokemon.ExpirationTimestampMs; _spawnPointId = pokemon.SpawnPointId; _encounterId = pokemon.EncounterId; } // Calling from CatchLurePokemon else if (encounter is DiskEncounterResponse && encounter?.Result == DiskEncounterResponse.Types.Result.Success && !(currentFortData == null)) { encounteredPokemon = encounter?.PokemonData; unixTimeStamp = currentFortData.LureInfo.LureExpiresTimestampMs; _spawnPointId = currentFortData.Id; _encounterId = currentFortData.LureInfo.EncounterId; } else { return(true); // No success to work with, exit } // Check for pokeballs before proceeding var pokeball = await GetBestBall(session, encounteredPokemon, probability).ConfigureAwait(false); if (pokeball == ItemId.ItemUnknown) { Logger.Write(session.Translation.GetTranslation(TranslationString.ZeroPokeballInv)); return(false); } // Calculate CP and IV var pokemonCp = encounteredPokemon?.Cp; var pokemonIv = PokemonInfo.CalculatePokemonPerfection(encounteredPokemon); var lv = PokemonInfo.GetLevel(encounteredPokemon); // Calculate distance away var latitude = encounter is EncounterResponse || encounter is IncenseEncounterResponse ? pokemon.Latitude : currentFortData.Latitude; var longitude = encounter is EncounterResponse || encounter is IncenseEncounterResponse ? pokemon.Longitude : currentFortData.Longitude; var distance = LocationUtils.CalculateDistanceInMeters(session.Client.CurrentLatitude, session.Client.CurrentLongitude, latitude, longitude); if (session.LogicSettings.ActivateMSniper) { var newdata = new MSniperServiceTask.EncounterInfo() { EncounterId = _encounterId.ToString(), Iv = Math.Round(pokemonIv, 2), Latitude = latitude.ToString("G17", CultureInfo.InvariantCulture), Longitude = longitude.ToString("G17", CultureInfo.InvariantCulture), PokemonId = (int)(encounteredPokemon?.PokemonId ?? 0), PokemonName = encounteredPokemon?.PokemonId.ToString(), SpawnPointId = _spawnPointId, Move1 = PokemonInfo.GetPokemonMove1(encounteredPokemon).ToString(), Move2 = PokemonInfo.GetPokemonMove2(encounteredPokemon).ToString(), Expiration = unixTimeStamp }; session.EventDispatcher.Send(newdata); } DateTime expiredDate = new DateTime(1970, 1, 1, 0, 0, 0).AddMilliseconds(Convert.ToDouble(unixTimeStamp)); var encounterEV = new EncounteredEvent() { Latitude = latitude, Longitude = longitude, PokemonId = encounteredPokemon.PokemonId, IV = pokemonIv, Level = (int)lv, Expires = expiredDate.ToUniversalTime(), ExpireTimestamp = unixTimeStamp, SpawnPointId = _spawnPointId, EncounterId = _encounterId.ToString(), Move1 = PokemonInfo.GetPokemonMove1(encounteredPokemon).ToString(), Move2 = PokemonInfo.GetPokemonMove2(encounteredPokemon).ToString(), }; //add catch to avoid snipe duplicate string uniqueCacheKey = CatchPokemonTask.GetUsernameGeoLocationCacheKey(session.Settings.Username, encounterEV.PokemonId, encounterEV.Latitude, encounterEV.Longitude); session.Cache.Add(uniqueCacheKey, encounterEV, DateTime.Now.AddMinutes(30)); session.EventDispatcher.Send(encounterEV); if (IsNotMetWithCatchCriteria(session, encounteredPokemon, pokemonIv, lv, pokemonCp)) { session.EventDispatcher.Send(new NoticeEvent { Message = session.Translation.GetTranslation(TranslationString.PokemonSkipped, encounteredPokemon.PokemonId) }); session.Cache.Add(CatchPokemonTask.GetEncounterCacheKey(_encounterId), encounteredPokemon, expiredDate); Logger.Write( $"Filter catch not met. {encounteredPokemon.PokemonId.ToString()} IV {pokemonIv} lv {lv} {pokemonCp} move1 {PokemonInfo.GetPokemonMove1(encounteredPokemon)} move 2 {PokemonInfo.GetPokemonMove2(encounteredPokemon)}"); return(true); } CatchPokemonResponse caughtPokemonResponse = null; var lastThrow = CatchPokemonResponse.Types.CatchStatus.CatchSuccess; // Initializing lastThrow var attemptCounter = 1; // Main CatchPokemon-loop do { if (session.LogicSettings.UseHumanlikeDelays) { await DelayingUtils.DelayAsync(session.LogicSettings.BeforeCatchDelay, 0, session.CancellationTokenSource.Token).ConfigureAwait(false); } if ((session.LogicSettings.MaxPokeballsPerPokemon > 0 && attemptCounter > session.LogicSettings.MaxPokeballsPerPokemon)) { break; } pokeball = await GetBestBall(session, encounteredPokemon, probability).ConfigureAwait(false); if (pokeball == ItemId.ItemUnknown) { session.EventDispatcher.Send(new NoPokeballEvent { Id = encounter is EncounterResponse ? pokemon.PokemonId : encounter?.PokemonData.PokemonId, Cp = encounteredPokemon.Cp }); return(false); } // Determine whether to use berries or not if (lastThrow != CatchPokemonResponse.Types.CatchStatus.CatchMissed) { //AmountOfBerries++; //if (AmountOfBerries <= session.LogicSettings.MaxBerriesToUsePerPokemon) await UseBerry(session, encounterEV.PokemonId, _encounterId, _spawnPointId, pokemonIv, pokemonCp ?? 10000, //unknown CP pokemon, want to use berry encounterEV.Level, probability, cancellationToken).ConfigureAwait(false); } bool hitPokemon = true; //default to excellent throw var normalizedRecticleSize = 1.95; //default spin var spinModifier = 1.0; //Humanized throws if (session.LogicSettings.EnableHumanizedThrows) { //thresholds: https://gist.github.com/anonymous/077d6dea82d58b8febde54ae9729b1bf var spinTxt = "Curve"; var hitTxt = "Excellent"; if (pokemonCp > session.LogicSettings.ForceExcellentThrowOverCp || pokemonIv > session.LogicSettings.ForceExcellentThrowOverIv) { normalizedRecticleSize = Random.NextDouble() * (1.95 - 1.7) + 1.7; } else if (pokemonCp >= session.LogicSettings.ForceGreatThrowOverCp || pokemonIv >= session.LogicSettings.ForceGreatThrowOverIv) { normalizedRecticleSize = Random.NextDouble() * (1.95 - 1.3) + 1.3; hitTxt = "Great"; } else { var regularThrow = 100 - (session.LogicSettings.ExcellentThrowChance + session.LogicSettings.GreatThrowChance + session.LogicSettings.NiceThrowChance); var rnd = Random.Next(1, 101); if (rnd <= regularThrow) { normalizedRecticleSize = Random.NextDouble() * (1 - 0.1) + 0.1; hitTxt = "Ordinary"; } else if (rnd <= regularThrow + session.LogicSettings.NiceThrowChance) { normalizedRecticleSize = Random.NextDouble() * (1.3 - 1) + 1; hitTxt = "Nice"; } else if (rnd <= regularThrow + session.LogicSettings.NiceThrowChance + session.LogicSettings.GreatThrowChance) { normalizedRecticleSize = Random.NextDouble() * (1.7 - 1.3) + 1.3; hitTxt = "Great"; } if (Random.NextDouble() * 100 > session.LogicSettings.CurveThrowChance) { spinModifier = 0.0; spinTxt = "Straight"; } } // Round to 2 decimals normalizedRecticleSize = Math.Round(normalizedRecticleSize, 2); // Missed throw check int missChance = Random.Next(1, 101); if (missChance <= session.LogicSettings.ThrowMissPercentage && session.LogicSettings.EnableMissedThrows) { hitPokemon = false; } Logger.Write($"(Threw ball) {hitTxt} throw, {spinTxt}-ball, HitPokemon = {hitPokemon}...", LogLevel.Debug); } if (CatchFleeContinuouslyCount >= 3 && session.LogicSettings.ByPassCatchFlee) { MSniperServiceTask.BlockSnipe(); if (totalBalls <= BALL_REQUIRED_TO_BYPASS_CATCHFLEE) { Logger.Write("You don't have enough balls to bypass catchflee"); return(false); } List <ItemId> ballToByPass = new List <ItemId>(); var numPokeBalls = await session.Inventory.GetItemAmountByType(ItemId.ItemPokeBall).ConfigureAwait(false); for (int i = 0; i < numPokeBalls - 1; i++) { ballToByPass.Add(ItemId.ItemPokeBall); } var numGreatBalls = await session.Inventory.GetItemAmountByType(ItemId.ItemGreatBall).ConfigureAwait(false); for (int i = 0; i < numGreatBalls - 1; i++) { ballToByPass.Add(ItemId.ItemGreatBall); } var numUltraBalls = await session.Inventory.GetItemAmountByType(ItemId.ItemUltraBall).ConfigureAwait(false); for (int i = 0; i < numUltraBalls - 1; i++) { ballToByPass.Add(ItemId.ItemUltraBall); } bool catchMissed = true; Random r = new Random(); for (int i = 0; i < ballToByPass.Count - 1; i++) { if (i > 130 && r.Next(0, 100) <= 30) { catchMissed = false; } else { catchMissed = true; } caughtPokemonResponse = await session.Client.Encounter.CatchPokemon( encounter is EncounterResponse || encounter is IncenseEncounterResponse ?pokemon.EncounterId : _encounterId, encounter is EncounterResponse || encounter is IncenseEncounterResponse ?pokemon.SpawnPointId : currentFortData.Id, ballToByPass[i], 1.0, 1.0, !catchMissed).ConfigureAwait(false); await session.Inventory.UpdateInventoryItem(ballToByPass[i]).ConfigureAwait(false); await Task.Delay(100).ConfigureAwait(false); Logger.Write($"CatchFlee By pass : {ballToByPass[i].ToString()} , Attempt {i}, result {caughtPokemonResponse.Status}"); if (caughtPokemonResponse.Status != CatchPokemonResponse.Types.CatchStatus.CatchMissed) { session.SaveBallForByPassCatchFlee = false; CatchFleeContinuouslyCount = 0; break; } } } else { caughtPokemonResponse = await session.Client.Encounter.CatchPokemon( encounter is EncounterResponse || encounter is IncenseEncounterResponse ?pokemon.EncounterId : _encounterId, encounter is EncounterResponse || encounter is IncenseEncounterResponse ?pokemon.SpawnPointId : currentFortData.Id, pokeball, normalizedRecticleSize, spinModifier, hitPokemon).ConfigureAwait(false); await session.Inventory.UpdateInventoryItem(pokeball).ConfigureAwait(false); } var evt = new PokemonCaptureEvent() { Status = caughtPokemonResponse.Status, CaptureReason = caughtPokemonResponse.CaptureReason, Latitude = latitude, Longitude = longitude }; lastThrow = caughtPokemonResponse.Status; // sets lastThrow status if (caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchSuccess) { evt.Shiny = (await session.Inventory.GetPokemons().ConfigureAwait(false)).First(x => x.Id == caughtPokemonResponse.CapturedPokemonId).PokemonDisplay.Shiny ? "Yes" : "No"; evt.Form = (await session.Inventory.GetPokemons().ConfigureAwait(false)).First(x => x.Id == caughtPokemonResponse.CapturedPokemonId).PokemonDisplay.Form.ToString().Replace("Unown", "").Replace("Unset", "Normal"); evt.Costume = (await session.Inventory.GetPokemons().ConfigureAwait(false)).First(x => x.Id == caughtPokemonResponse.CapturedPokemonId).PokemonDisplay.Costume.ToString().Replace("Unset", "Regular"); evt.Gender = (await session.Inventory.GetPokemons().ConfigureAwait(false)).First(x => x.Id == caughtPokemonResponse.CapturedPokemonId).PokemonDisplay.Gender.ToString(); var totalExp = 0; var stardust = caughtPokemonResponse.CaptureAward.Stardust.Sum(); var totalStarDust = session.Inventory.UpdateStarDust(stardust); var CaptuerXP = caughtPokemonResponse.CaptureAward.Xp.Sum(); if (encounteredPokemon != null) { encounteredPokemon.Id = caughtPokemonResponse.CapturedPokemonId; } foreach (var xp in caughtPokemonResponse.CaptureAward.Xp) { totalExp += xp; } //This accounts for XP for CatchFlee if (totalExp < 1) { totalExp = 25; } evt.Exp = totalExp; evt.Stardust = stardust; evt.UniqueId = caughtPokemonResponse.CapturedPokemonId; evt.Candy = await session.Inventory.GetCandyFamily(pokemon.PokemonId).ConfigureAwait(false); evt.totalStarDust = totalStarDust; if (session.LogicSettings.AutoFavoriteShinyOnCatch) { if (evt.Shiny == "Yes") { await FavoritePokemonTask.Execute(session, encounteredPokemon.Id, true); Logger.Write($"You've caught a Shiny Pokemon ({encounteredPokemon.Nickname}) and it has been Favorited."); } } } if (caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchSuccess || caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchFlee) { // Also count catch flee against the catch limit if (session.LogicSettings.UseCatchLimit) { session.Stats.AddPokemonTimestamp(DateTime.Now.Ticks); session.EventDispatcher.Send(new CatchLimitUpdate(session.Stats.GetNumPokemonsInLast24Hours(), session.LogicSettings.CatchPokemonLimit)); } } evt.CatchType = encounter is EncounterResponse ? session.Translation.GetTranslation(TranslationString.CatchTypeNormal) : encounter is DiskEncounterResponse ? session.Translation.GetTranslation(TranslationString.CatchTypeLure) : session.Translation.GetTranslation(TranslationString.CatchTypeIncense); evt.CatchTypeText = encounter is EncounterResponse ? "normal" : encounter is DiskEncounterResponse ? "lure" : "incense"; evt.Id = encounter is EncounterResponse ? pokemon.PokemonId : encounter?.PokemonData.PokemonId; evt.EncounterId = _encounterId; evt.Move1 = PokemonInfo.GetPokemonMove1(encounteredPokemon); evt.Move2 = PokemonInfo.GetPokemonMove2(encounteredPokemon); evt.Expires = pokemon?.ExpirationTimestampMs ?? 0; evt.SpawnPointId = _spawnPointId; evt.Level = PokemonInfo.GetLevel(encounteredPokemon); evt.Cp = encounteredPokemon.Cp; evt.MaxCp = PokemonInfo.CalculateMaxCp(encounteredPokemon.PokemonId); evt.Perfection = Math.Round(PokemonInfo.CalculatePokemonPerfection(encounteredPokemon), 2); evt.Probability = Math.Round(probability * 100, 2); evt.Distance = distance; evt.Pokeball = pokeball; evt.Attempt = attemptCounter; //await session.Inventory.RefreshCachedInventory().ConfigureAwait(false); evt.BallAmount = await session.Inventory.GetItemAmountByType(pokeball).ConfigureAwait(false); evt.Rarity = PokemonGradeHelper.GetPokemonGrade(evt.Id).ToString(); session.EventDispatcher.Send(evt); attemptCounter++; // If Humanlike delays are used if (session.LogicSettings.UseHumanlikeDelays) { switch (caughtPokemonResponse.Status) { case CatchPokemonResponse.Types.CatchStatus.CatchError: await DelayingUtils.DelayAsync(session.LogicSettings.CatchErrorDelay, 0, session.CancellationTokenSource.Token).ConfigureAwait(false); break; case CatchPokemonResponse.Types.CatchStatus.CatchSuccess: await DelayingUtils.DelayAsync(session.LogicSettings.CatchSuccessDelay, 0, session.CancellationTokenSource.Token).ConfigureAwait(false); break; case CatchPokemonResponse.Types.CatchStatus.CatchEscape: await DelayingUtils.DelayAsync(session.LogicSettings.CatchEscapeDelay, 0, session.CancellationTokenSource.Token).ConfigureAwait(false); break; case CatchPokemonResponse.Types.CatchStatus.CatchFlee: await DelayingUtils.DelayAsync(session.LogicSettings.CatchFleeDelay, 0, session.CancellationTokenSource.Token).ConfigureAwait(false); break; case CatchPokemonResponse.Types.CatchStatus.CatchMissed: await DelayingUtils.DelayAsync(session.LogicSettings.CatchMissedDelay, 0, session.CancellationTokenSource.Token).ConfigureAwait(false); break; default: break; } } else { await DelayingUtils.DelayAsync(session.LogicSettings.DelayBetweenPlayerActions, 0, session.CancellationTokenSource.Token).ConfigureAwait(false); } } while (caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchMissed || caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape); if (caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchFlee) { CatchFleeContinuouslyCount++; if (CatchFleeContinuouslyCount >= 3 && session.LogicSettings.ByPassCatchFlee) { session.SaveBallForByPassCatchFlee = true; Logger.Write("Seem that bot has been catch flee softban, Bot will start save 100 balls to by pass it."); } if (manager.AllowMultipleBot() && !session.LogicSettings.ByPassCatchFlee) { if (CatchFleeContinuouslyCount > session.LogicSettings.MultipleBotConfig.CatchFleeCount && TinyIoCContainer.Current.Resolve <MultiAccountManager>().AllowSwitch()) { CatchFleeContinuouslyCount = 0; session.SaveBallForByPassCatchFlee = false; throw new ActiveSwitchByRuleException() { MatchedRule = SwitchRules.CatchFlee, ReachedValue = session.LogicSettings.MultipleBotConfig.CatchFleeCount }; } } } else { //reset if not catch flee. if (caughtPokemonResponse.Status != CatchPokemonResponse.Types.CatchStatus.CatchMissed) { CatchFleeContinuouslyCount = 0; MSniperServiceTask.UnblockSnipe(); } } session.Actions.RemoveAll(x => x == BotActions.Catch); if (MultipleBotConfig.IsMultiBotActive(session.LogicSettings, manager)) { ExecuteSwitcher(session, encounterEV); } if (session.LogicSettings.TransferDuplicatePokemonOnCapture && session.LogicSettings.TransferDuplicatePokemon && sessionAllowTransfer && caughtPokemonResponse != null && caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchSuccess) { if (session.LogicSettings.UseNearActionRandom) { await HumanRandomActionTask.TransferRandom(session, cancellationToken).ConfigureAwait(false); } else { await TransferDuplicatePokemonTask.Execute(session, cancellationToken).ConfigureAwait(false); } } } return(true); }
/// <summary> /// Because this function sometime being called inside loop, return true it mean we don't want break look, false it mean not need to call this , break a loop from caller function /// </summary> /// <param name="session"></param> /// <param name="cancellationToken"></param> /// <param name="encounter"></param> /// <param name="pokemon"></param> /// <param name="currentFortData"></param> /// <param name="sessionAllowTransfer"></param> /// <returns></returns> public static async Task <bool> Execute(ISession session, CancellationToken cancellationToken, dynamic encounter, MapPokemon pokemon, FortData currentFortData, bool sessionAllowTransfer) { // If the encounter is null nothing will work below, so exit now if (encounter == null) { return(true); } // Exit if user defined max limits reached if (session.Stats.CatchThresholdExceeds(session)) { if (session.LogicSettings.AllowMultipleBot && session.LogicSettings.MultipleBotConfig.SwitchOnCatchLimit) { throw new ActiveSwitchByRuleException() { MatchedRule = SwitchRules.CatchLimitReached, ReachedValue = session.LogicSettings.CatchPokemonLimit }; } return(false); } using (var block = new BlockableScope(session, BotActions.Catch)) { if (!await block.WaitToRun()) { return(true); } AmountOfBerries = 0; cancellationToken.ThrowIfCancellationRequested(); float probability = encounter.CaptureProbability?.CaptureProbability_[0]; PokemonData encounteredPokemon; long unixTimeStamp; ulong _encounterId; string _spawnPointId; // Calling from CatchNearbyPokemonTask and SnipePokemonTask if (encounter is EncounterResponse && (encounter?.Status == EncounterResponse.Types.Status.EncounterSuccess)) { encounteredPokemon = encounter.WildPokemon?.PokemonData; unixTimeStamp = encounter.WildPokemon?.LastModifiedTimestampMs + encounter.WildPokemon?.TimeTillHiddenMs; _spawnPointId = encounter.WildPokemon?.SpawnPointId; _encounterId = encounter.WildPokemon?.EncounterId; } // Calling from CatchIncensePokemonTask else if (encounter is IncenseEncounterResponse && (encounter?.Result == IncenseEncounterResponse.Types.Result.IncenseEncounterSuccess)) { encounteredPokemon = encounter?.PokemonData; unixTimeStamp = pokemon.ExpirationTimestampMs; _spawnPointId = pokemon.SpawnPointId; _encounterId = pokemon.EncounterId; } // Calling from CatchLurePokemon else if (encounter is DiskEncounterResponse && encounter?.Result == DiskEncounterResponse.Types.Result.Success && !(currentFortData == null)) { encounteredPokemon = encounter?.PokemonData; unixTimeStamp = currentFortData.LureInfo.LureExpiresTimestampMs; _spawnPointId = currentFortData.Id; _encounterId = currentFortData.LureInfo.EncounterId; } else { return(true); // No success to work with, exit } // Check for pokeballs before proceeding var pokeball = await GetBestBall(session, encounteredPokemon, probability); if (pokeball == ItemId.ItemUnknown) { Logger.Write(session.Translation.GetTranslation(TranslationString.ZeroPokeballInv)); return(false); } // Calculate CP and IV var pokemonCp = encounteredPokemon?.Cp; var pokemonIv = PokemonInfo.CalculatePokemonPerfection(encounteredPokemon); var lv = PokemonInfo.GetLevel(encounteredPokemon); // Calculate distance away var latitude = encounter is EncounterResponse || encounter is IncenseEncounterResponse ? pokemon.Latitude : currentFortData.Latitude; var longitude = encounter is EncounterResponse || encounter is IncenseEncounterResponse ? pokemon.Longitude : currentFortData.Longitude; var distance = LocationUtils.CalculateDistanceInMeters(session.Client.CurrentLatitude, session.Client.CurrentLongitude, latitude, longitude); if (session.LogicSettings.ActivateMSniper) { var newdata = new MSniperServiceTask.EncounterInfo(); newdata.EncounterId = _encounterId.ToString(); newdata.Iv = Math.Round(pokemonIv, 2); newdata.Latitude = latitude.ToString("G17", CultureInfo.InvariantCulture); newdata.Longitude = longitude.ToString("G17", CultureInfo.InvariantCulture); newdata.PokemonId = (int)(encounteredPokemon?.PokemonId ?? 0); newdata.PokemonName = encounteredPokemon?.PokemonId.ToString(); newdata.SpawnPointId = _spawnPointId; newdata.Move1 = PokemonInfo.GetPokemonMove1(encounteredPokemon).ToString(); newdata.Move2 = PokemonInfo.GetPokemonMove2(encounteredPokemon).ToString(); newdata.Expiration = unixTimeStamp; session.EventDispatcher.Send(newdata); } DateTime expiredDate = new DateTime(1970, 1, 1, 0, 0, 0).AddMilliseconds(Convert.ToDouble(unixTimeStamp)); var encounterEV = new EncounteredEvent() { Latitude = latitude, Longitude = longitude, PokemonId = encounteredPokemon.PokemonId, IV = pokemonIv, Level = (int)lv, Expires = expiredDate.ToUniversalTime(), ExpireTimestamp = unixTimeStamp, SpawnPointId = _spawnPointId, EncounterId = _encounterId.ToString(), Move1 = PokemonInfo.GetPokemonMove1(encounteredPokemon).ToString(), Move2 = PokemonInfo.GetPokemonMove2(encounteredPokemon).ToString(), }; //add catch to avoid snipe duplicate string uniqueCacheKey = $"{session.Settings.PtcUsername}{session.Settings.GoogleUsername}{Math.Round(encounterEV.Latitude, 6)}{encounterEV.PokemonId}{Math.Round(encounterEV.Longitude, 6)}"; session.Cache.Add(uniqueCacheKey, encounterEV, DateTime.Now.AddMinutes(15)); session.EventDispatcher.Send(encounterEV); if (IsNotMetWithCatchCriteria(session, encounteredPokemon, pokemonIv, lv, pokemonCp)) { session.EventDispatcher.Send(new NoticeEvent { Message = session.Translation.GetTranslation(TranslationString.PokemonSkipped, encounteredPokemon.PokemonId) }); session.Cache.Add(_encounterId.ToString(), encounteredPokemon, expiredDate); Logger.Write( $"Filter catch not met. {encounteredPokemon.PokemonId.ToString()} IV {pokemonIv} lv {lv} {pokemonCp} move1 {PokemonInfo.GetPokemonMove1(encounteredPokemon)} move 2 {PokemonInfo.GetPokemonMove2(encounteredPokemon)}"); return(true); } CatchPokemonResponse caughtPokemonResponse = null; var lastThrow = CatchPokemonResponse.Types.CatchStatus.CatchSuccess; // Initializing lastThrow var attemptCounter = 1; // Main CatchPokemon-loop do { if ((session.LogicSettings.MaxPokeballsPerPokemon > 0 && attemptCounter > session.LogicSettings.MaxPokeballsPerPokemon)) { break; } pokeball = await GetBestBall(session, encounteredPokemon, probability); if (pokeball == ItemId.ItemUnknown) { session.EventDispatcher.Send(new NoPokeballEvent { Id = encounter is EncounterResponse ? pokemon.PokemonId : encounter?.PokemonData.PokemonId, Cp = encounteredPokemon.Cp }); return(false); } // Determine whether to use berries or not if (((session.LogicSettings.UseBerriesOperator.ToLower().Equals("and") && pokemonIv >= session.LogicSettings.UseBerriesMinIv && pokemonCp >= session.LogicSettings.UseBerriesMinCp && probability < session.LogicSettings.UseBerriesBelowCatchProbability) || (session.LogicSettings.UseBerriesOperator.ToLower().Equals("or") && ( pokemonIv >= session.LogicSettings.UseBerriesMinIv || pokemonCp >= session.LogicSettings.UseBerriesMinCp || probability < session.LogicSettings.UseBerriesBelowCatchProbability))) && // if last throw is a miss, no double berry lastThrow != CatchPokemonResponse.Types.CatchStatus.CatchMissed) { AmountOfBerries++; if (AmountOfBerries <= session.LogicSettings.MaxBerriesToUsePerPokemon) { await UseBerry(session, _encounterId, _spawnPointId, cancellationToken); } } bool hitPokemon = true; //default to excellent throw var normalizedRecticleSize = 1.95; //default spin var spinModifier = 1.0; //Humanized throws if (session.LogicSettings.EnableHumanizedThrows) { //thresholds: https://gist.github.com/anonymous/077d6dea82d58b8febde54ae9729b1bf var spinTxt = "Curve"; var hitTxt = "Excellent"; if (pokemonCp > session.LogicSettings.ForceExcellentThrowOverCp || pokemonIv > session.LogicSettings.ForceExcellentThrowOverIv) { normalizedRecticleSize = Random.NextDouble() * (1.95 - 1.7) + 1.7; } else if (pokemonCp >= session.LogicSettings.ForceGreatThrowOverCp || pokemonIv >= session.LogicSettings.ForceGreatThrowOverIv) { normalizedRecticleSize = Random.NextDouble() * (1.95 - 1.3) + 1.3; hitTxt = "Great"; } else { var regularThrow = 100 - (session.LogicSettings.ExcellentThrowChance + session.LogicSettings.GreatThrowChance + session.LogicSettings.NiceThrowChance); var rnd = Random.Next(1, 101); if (rnd <= regularThrow) { normalizedRecticleSize = Random.NextDouble() * (1 - 0.1) + 0.1; hitTxt = "Ordinary"; } else if (rnd <= regularThrow + session.LogicSettings.NiceThrowChance) { normalizedRecticleSize = Random.NextDouble() * (1.3 - 1) + 1; hitTxt = "Nice"; } else if (rnd <= regularThrow + session.LogicSettings.NiceThrowChance + session.LogicSettings.GreatThrowChance) { normalizedRecticleSize = Random.NextDouble() * (1.7 - 1.3) + 1.3; hitTxt = "Great"; } if (Random.NextDouble() * 100 > session.LogicSettings.CurveThrowChance) { spinModifier = 0.0; spinTxt = "Straight"; } } // Round to 2 decimals normalizedRecticleSize = Math.Round(normalizedRecticleSize, 2); // Missed throw check int missChance = Random.Next(1, 101); if (missChance <= session.LogicSettings.ThrowMissPercentage && session.LogicSettings.EnableMissedThrows) { hitPokemon = false; } Logger.Write($"(Threw ball) {hitTxt} throw, {spinTxt}-ball, HitPokemon = {hitPokemon}...", LogLevel.Debug); } caughtPokemonResponse = await session.Client.Encounter.CatchPokemon( encounter is EncounterResponse || encounter is IncenseEncounterResponse ?pokemon.EncounterId : _encounterId, encounter is EncounterResponse || encounter is IncenseEncounterResponse ?pokemon.SpawnPointId : currentFortData.Id, pokeball, normalizedRecticleSize, spinModifier, hitPokemon); await session.Inventory.UpdateInventoryItem(pokeball, -1); var evt = new PokemonCaptureEvent() { Status = caughtPokemonResponse.Status, Latitude = latitude, Longitude = longitude }; lastThrow = caughtPokemonResponse.Status; // sets lastThrow status if (caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchSuccess) { var totalExp = 0; var totalStartDust = caughtPokemonResponse.CaptureAward.Stardust.Sum(); if (encounteredPokemon != null) { encounteredPokemon.Id = caughtPokemonResponse.CapturedPokemonId; await session.Inventory.AddPokemonToCache(encounteredPokemon); } foreach (var xp in caughtPokemonResponse.CaptureAward.Xp) { totalExp += xp; } var stardust = session.Inventory.UpdateStartDust(totalStartDust); evt.Exp = totalExp; evt.Stardust = stardust; evt.UniqueId = caughtPokemonResponse.CapturedPokemonId; var pokemonSettings = await session.Inventory.GetPokemonSettings(); var pokemonFamilies = await session.Inventory.GetPokemonFamilies(); var setting = pokemonSettings.FirstOrDefault(q => pokemon != null && q.PokemonId == pokemon.PokemonId); var family = pokemonFamilies.FirstOrDefault(q => setting != null && q.FamilyId == setting.FamilyId); if (family != null) { await session.Inventory.UpdateCandy(family, caughtPokemonResponse.CaptureAward.Candy.Sum()); family.Candy_ += caughtPokemonResponse.CaptureAward.Candy.Sum(); evt.FamilyCandies = family.Candy_; } else { evt.FamilyCandies = caughtPokemonResponse.CaptureAward.Candy.Sum(); } if (session.LogicSettings.UseCatchLimit) { session.Stats.AddPokemonTimestamp(DateTime.Now.Ticks); Logger.Write( $"(CATCH LIMIT) {session.Stats.GetNumPokemonsInLast24Hours()}/{session.LogicSettings.CatchPokemonLimit}", LogLevel.Info, ConsoleColor.Yellow); } } evt.CatchType = encounter is EncounterResponse ? session.Translation.GetTranslation(TranslationString.CatchTypeNormal) : encounter is DiskEncounterResponse ? session.Translation.GetTranslation(TranslationString.CatchTypeLure) : session.Translation.GetTranslation(TranslationString.CatchTypeIncense); evt.CatchTypeText = encounter is EncounterResponse ? "normal" : encounter is DiskEncounterResponse ? "lure" : "incense"; evt.Id = encounter is EncounterResponse ? pokemon.PokemonId : encounter?.PokemonData.PokemonId; evt.EncounterId = _encounterId; evt.Move1 = PokemonInfo.GetPokemonMove1(encounteredPokemon); evt.Move2 = PokemonInfo.GetPokemonMove2(encounteredPokemon); evt.Expires = pokemon?.ExpirationTimestampMs ?? 0; evt.SpawnPointId = _spawnPointId; evt.Level = PokemonInfo.GetLevel(encounteredPokemon); evt.Cp = encounteredPokemon.Cp; evt.MaxCp = PokemonInfo.CalculateMaxCp(encounteredPokemon); evt.Perfection = Math.Round(PokemonInfo.CalculatePokemonPerfection(encounteredPokemon)); evt.Probability = Math.Round(probability * 100, 2); evt.Distance = distance; evt.Pokeball = pokeball; evt.Attempt = attemptCounter; //await session.Inventory.RefreshCachedInventory(); evt.BallAmount = await session.Inventory.GetItemAmountByType(pokeball); evt.Rarity = PokemonGradeHelper.GetPokemonGrade(evt.Id).ToString(); session.EventDispatcher.Send(evt); attemptCounter++; DelayingUtils.Delay(session.LogicSettings.DelayBetweenPlayerActions, 0); } while (caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchMissed || caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape); if (session.LogicSettings.AllowMultipleBot) { if (caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchFlee) { CatchFleeContinuouslyCount++; if (CatchFleeContinuouslyCount > session.LogicSettings.MultipleBotConfig.CatchFleeCount) { CatchFleeContinuouslyCount = 0; throw new ActiveSwitchByRuleException() { MatchedRule = SwitchRules.CatchFlee, ReachedValue = session.LogicSettings.MultipleBotConfig.CatchFleeCount }; } } else { //reset if not catch flee. CatchFleeContinuouslyCount = 0; MSniperServiceTask.UnblockSnipe(); } } session.Actions.RemoveAll(x => x == BotActions.Catch); if (MultipleBotConfig.IsMultiBotActive(session.LogicSettings)) { ExecuteSwitcher(session, encounterEV); } if (session.LogicSettings.TransferDuplicatePokemonOnCapture && session.LogicSettings.TransferDuplicatePokemon && sessionAllowTransfer && caughtPokemonResponse != null && caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchSuccess) { if (session.LogicSettings.UseNearActionRandom) { await HumanRandomActionTask.TransferRandom(session, cancellationToken); } else { await TransferDuplicatePokemonTask.Execute(session, cancellationToken); } } } return(true); }
public static ulong CatchPokemon(ulong encounterId, string spawnpointId, PokemonId pokeid, double pokeLong = 0, double pokeLat = 0, bool goBack = false, double returnLatitude = -1, double returnLongitude = -1, int luredPoke = 0) { ulong ret = 0; EncounterResponse encounterPokemonResponse; //Offset Miss count here to account for user setting. var missCount = 0; if (GlobalVars.Max_Missed_throws <= 1) { missCount = 2; } if (GlobalVars.Max_Missed_throws == 2) { missCount = 1; } var forceHit = false; try { if (luredPoke == 0) { encounterPokemonResponse = client.Encounter.EncounterPokemon(encounterId, spawnpointId).Result; } else if (luredPoke == 1) { var DiscEncounterPokemonResponse = client.Encounter.EncounterLurePokemon(encounterId, spawnpointId); encounterPokemonResponse = new EncounterResponse(); encounterPokemonResponse.Status = DiskEncounterResultToEncounterStatus(DiscEncounterPokemonResponse.Result); if (DiscEncounterPokemonResponse.Result == DiskEncounterResponse.Types.Result.Success) { encounterPokemonResponse.WildPokemon = new WildPokemon(); encounterPokemonResponse.WildPokemon.EncounterId = encounterId; encounterPokemonResponse.WildPokemon.PokemonData = DiscEncounterPokemonResponse.PokemonData; encounterPokemonResponse.CaptureProbability = new POGOProtos.Data.Capture.CaptureProbability(); encounterPokemonResponse.CaptureProbability.CaptureProbability_.Add(1.0F); } } else { var IncenseEncounterPokemonResponse = client.Encounter.EncounterIncensePokemon(encounterId, spawnpointId); encounterPokemonResponse = new EncounterResponse(); encounterPokemonResponse.Status = IncenseEncounterResultToEncounterStatus(IncenseEncounterPokemonResponse.Result); if (IncenseEncounterPokemonResponse.Result == IncenseEncounterResponse.Types.Result.IncenseEncounterSuccess) { encounterPokemonResponse.WildPokemon = new WildPokemon(); encounterPokemonResponse.WildPokemon.EncounterId = encounterId; encounterPokemonResponse.WildPokemon.PokemonData = IncenseEncounterPokemonResponse.PokemonData; encounterPokemonResponse.CaptureProbability = IncenseEncounterPokemonResponse.CaptureProbability; } } } catch (Exception ex) { Logger.ColoredConsoleWrite(ConsoleColor.Red, $"Error: Logic.cs - CatchPokemon - encounter: {ex.Message}"); if (goBack) { Logger.ColoredConsoleWrite(ConsoleColor.Cyan, $"(SNIPING) Go to {returnLatitude} / {returnLongitude} before starting the capture."); Logger.ColoredConsoleWrite(ConsoleColor.Cyan, LocationUtils.FindAddress(returnLatitude, returnLongitude)); LocationUtils.updatePlayerLocation(client, returnLatitude, returnLongitude, GlobalVars.altitude); var tmpMap = client.Map.GetMapObjects(true); } return(ret); } if (goBack) { Logger.ColoredConsoleWrite(ConsoleColor.Cyan, $"(SNIPING) Go to {returnLatitude} / {returnLongitude} before starting the capture."); Logger.ColoredConsoleWrite(ConsoleColor.Cyan, LocationUtils.FindAddress(returnLatitude, returnLongitude)); LocationUtils.updatePlayerLocation(client, returnLatitude, returnLongitude, GlobalVars.altitude); var tmpMap = client.Map.GetMapObjects(true); } if (encounterPokemonResponse.Status == EncounterResponse.Types.Status.EncounterSuccess) { if (SkippedPokemon.Contains(encounterPokemonResponse.WildPokemon.EncounterId)) { Logger.ColoredConsoleWrite(ConsoleColor.Cyan, "Previously Skipped this Pokemon - Skipping Again!"); return(0); } var bestPokeball = GetBestBall(encounterPokemonResponse?.WildPokemon, false); var iv = PokemonGo.RocketAPI.PokemonInfo.CalculatePokemonPerfection(encounterPokemonResponse.WildPokemon.PokemonData); var strIVPerfection = iv.ToString("0.00"); if (bestPokeball == ItemId.ItemUnknown) { Logger.ColoredConsoleWrite(ConsoleColor.Red, $"No Pokeballs! - missed {pokeid} CP {encounterPokemonResponse?.WildPokemon?.PokemonData?.Cp} IV {strIVPerfection}%"); Logger.ColoredConsoleWrite(ConsoleColor.Red, "Detected all balls out of stock - disabling pokemon catch until restock of at least 1 ball type occurs"); Logic.Instance.pokeballoutofstock = true; AllowCatchPokemon = false; return(0); } var inventoryBerries = client.Inventory.GetItems(); var probability = encounterPokemonResponse?.CaptureProbability?.CaptureProbability_?.FirstOrDefault(); var probability100 = Math.Round(probability.Value * 100); Logger.ColoredConsoleWrite(ConsoleColor.Magenta, $"Encountered {pokeid} CP {encounterPokemonResponse?.WildPokemon?.PokemonData?.Cp} IV {strIVPerfection}% Probability {probability100}%"); if (encounterPokemonResponse.WildPokemon.PokemonData != null) { SaveLocations(encounterPokemonResponse.WildPokemon, iv, probability100); } if (encounterPokemonResponse.WildPokemon.PokemonData != null && encounterPokemonResponse.WildPokemon.PokemonData.Cp >= GlobalVars.MinCPtoCatch && probability100 >= GlobalVars.MinProbToCatch && iv >= GlobalVars.MinIVtoCatch) { var usedBerry = false; var escaped = false; CatchPokemonResponse caughtPokemonResponse; var inventory = client.Inventory.GetItems(); var razz = inventory.FirstOrDefault(p => p.ItemId == ItemId.ItemRazzBerry); var pinap = inventory.FirstOrDefault(p => p.ItemId == ItemId.ItemPinapBerry); var nanab = inventory.FirstOrDefault(p => p.ItemId == ItemId.ItemNanabBerry); do { // Check if the best ball is still valid if (bestPokeball == ItemId.ItemUnknown) { Logger.ColoredConsoleWrite(ConsoleColor.Red, $"No Pokeballs! - missed {pokeid} CP {encounterPokemonResponse?.WildPokemon?.PokemonData?.Cp} IV {strIVPerfection}%"); Logger.ColoredConsoleWrite(ConsoleColor.Red, "Detected all balls out of stock - disabling pokemon catch until restock of at least 1 ball type occurs"); Logic.Instance.pokeballoutofstock = true; AllowCatchPokemon = false; return(0); } if (GlobalVars.UseRazzBerry && !usedBerry && (probability.Value < GlobalVars.razzberry_chance)) { if (razz != null && razz.Count > 0) { //Throw berry var useRazzberry = client.Encounter.UseItemEncounter(encounterId, ItemId.ItemRazzBerry, spawnpointId); if (useRazzberry.Status == UseItemEncounterResponse.Types.Status.Success) { razz.Count = razz.Count - 1; Logger.Info($"We used a Razz Berry. Remaining: {razz.Count}."); usedBerry = true; } else { Logger.Info("RazzBerry Status: " + useRazzberry.Status); } RandomHelper.RandomSleep(250); } if (!client.Player.PlayerResponse.PlayerData.TutorialState.Contains(TutorialState.PokemonBerry)) { Logic.Instance.Tutorial.MarkTutorialAsDone(TutorialState.PokemonBerry, client); } } if (GlobalVars.PokemonPinap.Contains(pokeid) && !usedBerry) { try { if (pinap != null && pinap.Count > 0) { // Use a pinap var res = client.Encounter.UseItemEncounter(encounterId, ItemId.ItemPinapBerry, spawnpointId); if (res.Status == UseItemEncounterResponse.Types.Status.Success) { pinap.Count = pinap.Count - 1; Logger.Info($"We used a Pinap Berry. Remaining: {pinap.Count}."); usedBerry = true; } else { Logger.Info("PinapBerry Status: " + res.Status); } RandomHelper.RandomSleep(250); } } catch (Exception ex1) { Logger.Debug("" + ex1); } } var r = new Random(); if (GlobalVars.UseNanabBerry && !usedBerry) { try { var reallyUseIt = (r.Next(0, 100) <= GlobalVars.NanabPercent); if (GlobalVars.NanabPercent == 100 || reallyUseIt) { if (nanab != null && nanab.Count > 0) { var res = client.Encounter.UseItemEncounter(encounterId, ItemId.ItemNanabBerry, spawnpointId); if (res.Status == UseItemEncounterResponse.Types.Status.Success) { nanab.Count = nanab.Count - 1; Logger.Info($"We used a Nabab Berry. Remaining: {nanab.Count}."); usedBerry = true; } else { Logger.Info("Status: " + res.Status); } RandomHelper.RandomSleep(250); } } } catch (Exception ex1) { Logger.Debug("" + ex1); } } // limit number of balls wasted by misses and log for UX because fools be tripin switch (missCount) { case 0: if (bestPokeball == ItemId.ItemMasterBall) { Logger.ColoredConsoleWrite(ConsoleColor.Magenta, "No messing around with your Master Balls! Forcing a hit on target."); forceHit = true; } break; case 1: if (bestPokeball == ItemId.ItemUltraBall) { Logger.ColoredConsoleWrite(ConsoleColor.Magenta, "Not wasting more of your Ultra Balls! Forcing a hit on target."); forceHit = true; } break; case 2: //adding another chance of forcing hit here to improve overall odds after 2 misses var rInt = r.Next(0, 2); forceHit |= rInt == 1; break; default: // default to force hit after 3 wasted balls of any kind. Logger.ColoredConsoleWrite(ConsoleColor.Magenta, "Enough misses! Forcing a hit on target."); forceHit = true; break; } if (missCount > 0) { //adding another chance of forcing hit here to improve overall odds after 1st miss var rInt = r.Next(0, 3); if (rInt == 1) { // lets hit forceHit = true; } } caughtPokemonResponse = CatchPokemonWithRandomVariables(encounterId, spawnpointId, bestPokeball, forceHit); if (caughtPokemonResponse == null) { caughtPokemonResponse = new CatchPokemonResponse(); } if (caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchMissed) { Logger.ColoredConsoleWrite(ConsoleColor.Magenta, $"Missed { pokeid} while using {bestPokeball}"); missCount++; RandomHelper.RandomSleep(1500, 3000); } else if (caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape) { Logger.ColoredConsoleWrite(ConsoleColor.Magenta, $"{pokeid} escaped while using {bestPokeball}"); usedBerry = false; escaped = true; //reset forceHit in case we randomly triggered on last throw. forceHit = false; RandomHelper.RandomSleep(1500, 3000); } // Update the best ball to ensure we can still throw bestPokeball = GetBestBall(encounterPokemonResponse?.WildPokemon, escaped); } while (caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchMissed || caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape); if (caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchSuccess) { ret = caughtPokemonResponse.CapturedPokemonId; if (GlobalVars.ShowPokemons) { Logic.Instance.DeletePokemonFromMap(encounterPokemonResponse.WildPokemon.SpawnPointId); } var curDate = DateTime.Now; Task.Factory.StartNew(() => infoObservable.PushNewHuntStats($"{pokeLat}/{pokeLong};{pokeid};{curDate.Ticks};{curDate}" + Environment.NewLine)); var date = DateTime.Now; if (caughtPokemonResponse.CaptureAward.Xp.Sum() >= 500) { if (GlobalVars.LogPokemons) { File.AppendAllText(GlobalVars.FileForPokemonsCaught, $"[{date}] Caught new {pokeid} (CP: {encounterPokemonResponse?.WildPokemon?.PokemonData?.Cp} | IV: {strIVPerfection}% | Pokeball used: {bestPokeball} | XP: {caughtPokemonResponse.CaptureAward.Xp.Sum()}) " + Environment.NewLine); } Logger.ColoredConsoleWrite(ConsoleColor.Gray, $"Caught {pokeid} CP {encounterPokemonResponse?.WildPokemon?.PokemonData?.Cp} IV {strIVPerfection}% got {caughtPokemonResponse.CaptureAward.Xp.Sum()} XP | {caughtPokemonResponse.CaptureAward.Candy.Sum()} Candies | {caughtPokemonResponse.CaptureAward.Stardust.Sum()} Stardust"); Setout.pokemonCatchCount++; Setout.SaveSession(); // Wrong: TutorialState.PokemonCapture is not for the first wild pokemon caught. // if (!client.Player.PlayerResponse.PlayerData.TutorialState.Contains(TutorialState.PokemonCapture)) Logic.Instance.Tutorial.MarkTutorialAsDone(TutorialState.PokemonCapture, client, pokeid); } else { if (GlobalVars.LogPokemons) { File.AppendAllText(GlobalVars.FileForPokemonsCaught, $"[{date}] Caught {pokeid} (CP: {encounterPokemonResponse?.WildPokemon?.PokemonData?.Cp} | IV: {strIVPerfection}% | Pokeball used: {bestPokeball} | XP: {caughtPokemonResponse.CaptureAward.Xp.Sum()}) " + Environment.NewLine); } Logger.ColoredConsoleWrite(ConsoleColor.Gray, $"Caught {pokeid} CP {encounterPokemonResponse?.WildPokemon?.PokemonData?.Cp} IV {strIVPerfection}% got {caughtPokemonResponse.CaptureAward.Xp.Sum()} XP | {caughtPokemonResponse.CaptureAward.Candy.Sum()} Candies | {caughtPokemonResponse.CaptureAward.Stardust.Sum()} Stardust"); Setout.pokemonCatchCount++; Setout.SaveSession(); if (Logic.Instance.Telegram != null) { Logic.Instance.Telegram.sendInformationText(TelegramUtil.TelegramUtilInformationTopics.Catch, pokeid, encounterPokemonResponse?.WildPokemon?.PokemonData?.Cp, strIVPerfection, bestPokeball, caughtPokemonResponse.CaptureAward.Xp.Sum()); } } Logic.Instance.BotStats.AddPokemon(1); Logic.Instance.BotStats.AddExperience(caughtPokemonResponse.CaptureAward.Xp.Sum()); Logic.Instance.BotStats.AddStardust(caughtPokemonResponse.CaptureAward.Stardust.Sum()); Setout.RefreshConsoleTitle(client); RandomHelper.RandomSleep(1500, 2000); } else { Logger.ColoredConsoleWrite(ConsoleColor.DarkYellow, $"{pokeid} CP {encounterPokemonResponse?.WildPokemon?.PokemonData?.Cp} IV {strIVPerfection}% got away while using {bestPokeball}.."); Logic.FailedSoftban++; if (Logic.FailedSoftban > 10) { Logger.ColoredConsoleWrite(ConsoleColor.Red, $"Soft Ban Detected - Stopping Bot to prevent perma-ban. Try again in 4-24 hours and be more careful next time!"); Setout.LimitReached(""); } } } else { Logger.ColoredConsoleWrite(ConsoleColor.Magenta, "Pokemon CP or IV or Prob lower than Configured Min to Catch - Skipping Pokemon"); SkippedPokemon.Add(encounterPokemonResponse.WildPokemon.EncounterId); } } else if (encounterPokemonResponse.Status == EncounterResponse.Types.Status.PokemonInventoryFull) { Logger.Warning("You have no free space for new pokemons...transfer some as soon as possible."); } else { Logger.Debug(encounterPokemonResponse.Status.ToString()); } return(ret); }
//Catch encountered pokemon private async Task <MethodResult> CatchPokemon(dynamic eResponse, MapPokemon mapPokemon, bool snipped = false) { PokemonData _encounteredPokemon = null; long _unixTimeStamp = 0; ulong _encounterId = 0; string _spawnPointId = null; string _pokemonType = null; //Default catch success LoggerTypes _loggerType = LoggerTypes.Success; // Calling from CatchNormalPokemon if (eResponse is EncounterResponse && (eResponse?.Status == EncounterResponse.Types.Status.EncounterSuccess)) { _encounteredPokemon = eResponse.WildPokemon?.PokemonData; _unixTimeStamp = eResponse.WildPokemon?.LastModifiedTimestampMs + eResponse.WildPokemon?.TimeTillHiddenMs; _spawnPointId = eResponse.WildPokemon?.SpawnPointId; _encounterId = eResponse.WildPokemon?.EncounterId; _pokemonType = "Normal"; } // Calling from CatchIncensePokemon else if (eResponse is IncenseEncounterResponse && (eResponse?.Result == IncenseEncounterResponse.Types.Result.IncenseEncounterSuccess)) { _encounteredPokemon = eResponse?.PokemonData; _unixTimeStamp = mapPokemon.ExpirationTimestampMs; _spawnPointId = mapPokemon.SpawnPointId; _encounterId = mapPokemon.EncounterId; _pokemonType = "Incense"; } if (_encounterId == _lastPokeSniperId || snipped) { _pokemonType = "Local Snipe: " + _pokemonType; _loggerType = LoggerTypes.Snipe; AlreadySnipped = true; } CatchPokemonResponse catchPokemonResponse = null; int attemptCount = 1; bool berryUsed = false; if (_encounteredPokemon == null || _encounteredPokemon.PokemonId == PokemonId.Missingno) { return(new MethodResult()); } do { if (!CatchDisabled) { if (RemainingPokeballs() < 1) { LogCaller(new LoggerEventArgs("You don't have any pokeball catching pokemon will be disabled during " + UserSettings.DisableCatchDelay.ToString(CultureInfo.InvariantCulture) + " minutes.", LoggerTypes.Info)); CatchDisabled = true; TimeAutoCatch = DateTime.Now.AddMinutes(UserSettings.DisableCatchDelay); return(new MethodResult()); } } else { return(new MethodResult()); } //Uses lowest capture probability float probability = eResponse.CaptureProbability.CaptureProbability_[0]; ItemId pokeBall = GetBestBall(_encounteredPokemon); if (UserSettings.UseBerries) { bool isLowProbability = probability < 0.40; bool isHighCp = _encounteredPokemon.Cp > 800; bool isHighPerfection = CalculateIVPerfection(_encounteredPokemon) > 95; if (!berryUsed) { if ((isLowProbability && isHighCp) || isHighPerfection) { await UseBerry(mapPokemon, ItemId.ItemRazzBerry); berryUsed = true; } else { bool isHighProbability = probability > 0.65; var catchSettings = UserSettings.CatchSettings.FirstOrDefault(x => x.Id == _encounteredPokemon.PokemonId); if (isHighProbability && catchSettings.UsePinap) { await UseBerry(mapPokemon, ItemId.ItemPinapBerry); berryUsed = true; } else if (new Random().Next(0, 100) < 50) { // IF we dont use razz neither use pinap, then we will use nanab randomly the 50% of times. await UseBerry(mapPokemon, ItemId.ItemNanabBerry); berryUsed = true; } } await Task.Delay(CalculateDelay(UserSettings.DelayBetweenPlayerActions, UserSettings.PlayerActionDelayRandom)); } } await Task.Delay(CalculateDelay(UserSettings.DelayBetweenPlayerActions, UserSettings.PlayerActionDelayRandom)); double reticuleSize = 1.95; bool hitInsideReticule = true; //Humanization if (UserSettings.EnableHumanization) { reticuleSize = (double)_rand.Next(10, 195) / 100; hitInsideReticule = HitInsideReticle(); } var arPlusValues = new ARPlusEncounterValues(); if (UserSettings.GetArBonus) { LogCaller(new LoggerEventArgs("Using AR Bonus Values", LoggerTypes.Debug)); arPlusValues.Awareness = (float)UserSettings.ARBonusAwareness; arPlusValues.Proximity = (float)UserSettings.ARBonusProximity; arPlusValues.PokemonFrightened = false; } if (!_client.LoggedIn) { MethodResult result = await AcLogin(); if (!result.Success) { return(result); } } var catchresponse = await _client.ClientSession.RpcClient.SendRemoteProcedureCallAsync(new Request { RequestType = RequestType.CatchPokemon, RequestMessage = new CatchPokemonMessage { ArPlusValues = arPlusValues, EncounterId = _encounterId, HitPokemon = hitInsideReticule, NormalizedHitPosition = 1, NormalizedReticleSize = reticuleSize, Pokeball = pokeBall, SpawnPointId = _spawnPointId, SpinModifier = 1 }.ToByteString() }); if (catchresponse == null) { return(new MethodResult()); } catchPokemonResponse = CatchPokemonResponse.Parser.ParseFrom(catchresponse); string pokemon = String.Format("Name: {0}, CP: {1}, IV: {2:0.00}%", _encounteredPokemon.PokemonId.ToString(), _encounteredPokemon.Cp, CalculateIVPerfection(_encounteredPokemon)); string pokeBallName = pokeBall.ToString().Replace("Item", ""); switch (catchPokemonResponse.Status) { case CatchPokemonResponse.Types.CatchStatus.CatchError: LogCaller(new LoggerEventArgs(String.Format("Unknown Error. {0}. Attempt #{1}. Status: {2}", pokemon, attemptCount, catchPokemonResponse.Status), LoggerTypes.Warning)); continue; case CatchPokemonResponse.Types.CatchStatus.CatchEscape: //If we get this response, means we're good _fleeingPokemonResponses = 0; _potentialPokemonBan = false; if (AccountState == Enums.AccountState.SoftBan) { AccountState = Enums.AccountState.Good; LogCaller(new LoggerEventArgs("Pokemon ban was lifted", LoggerTypes.Info)); } LogCaller(new LoggerEventArgs(String.Format("Escaped ball. {0}. Attempt #{1}. Ball: {2}", pokemon, attemptCount, pokeBallName), LoggerTypes.PokemonEscape)); continue; case CatchPokemonResponse.Types.CatchStatus.CatchFlee: ++_fleeingPokemonResponses; LogCaller(new LoggerEventArgs(String.Format("Pokemon fled. {0}. Attempt #{1}. Ball: {2}", pokemon, attemptCount, pokeBallName), LoggerTypes.PokemonFlee)); continue; case CatchPokemonResponse.Types.CatchStatus.CatchMissed: LogCaller(new LoggerEventArgs(String.Format("Missed. {0}. Attempt #{1}. Status: {2}", pokemon, attemptCount, catchPokemonResponse.Status), LoggerTypes.Warning)); continue; case CatchPokemonResponse.Types.CatchStatus.CatchSuccess: //Reset data _fleeingPokemonResponses = 0; Tracker.AddValues(1, 0); _potentialPokemonBan = false; int expGained = catchPokemonResponse.CaptureAward.Xp.Sum(); int candyGained = catchPokemonResponse.CaptureAward.Candy.Sum(); ExpIncrease(expGained); //_expGained += expGained; LogCaller(new LoggerEventArgs(String.Format("[{0}] Pokemon Caught. {1}. Exp {2}. Candy: {3}. Attempt #{4}. Ball: {5}", _pokemonType, pokemon, expGained, candyGained, attemptCount, pokeBallName), _loggerType)); //Auto favorit shiny if (UserSettings.AutoFavoritShiny && _encounteredPokemon.PokemonDisplay.Shiny) { LogCaller(new LoggerEventArgs(String.Format("[{0}] Pokemon shiny. Auto favorit this pokemon.", _encounteredPokemon.PokemonId.ToString()), LoggerTypes.Info)); await FavoritePokemon(new List <PokemonData> { _encounteredPokemon }, true); await Task.Delay(CalculateDelay(UserSettings.DelayBetweenPlayerActions, UserSettings.PlayerActionDelayRandom)); } //Pokemon.Add(_encounteredPokemon); UpdateInventory(InventoryRefresh.Pokemon); UpdateInventory(InventoryRefresh.PokemonCandy); return(new MethodResult { Message = "Pokemon caught", Success = true }); } ++attemptCount; await Task.Delay(CalculateDelay(UserSettings.DelayBetweenPlayerActions, UserSettings.PlayerActionDelayRandom)); } while (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchMissed || catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape); return(new MethodResult()); }
//Catch lured pokemon private async Task <MethodResult> CatchPokemon(FortData fortData) { if (!_client.LoggedIn) { MethodResult result = await AcLogin(); if (!result.Success) { return(result); } } if (!CatchDisabled) { if (RemainingPokeballs() < 1) { LogCaller(new LoggerEventArgs("You don't have any pokeball catching (Lure) pokemon will be disabled during " + UserSettings.DisableCatchDelay.ToString(CultureInfo.InvariantCulture) + " minutes.", LoggerTypes.Info)); CatchDisabled = true; TimeAutoCatch = DateTime.Now.AddMinutes(UserSettings.DisableCatchDelay); return(new MethodResult()); } } else { return(new MethodResult()); } if (fortData.LureInfo == null || fortData.LureInfo.ActivePokemonId == PokemonId.Missingno) { return(new MethodResult()); } if (LastedEncountersIds.Contains(fortData.LureInfo.EncounterId)) { return(new MethodResult()); } var response = await _client.ClientSession.RpcClient.SendRemoteProcedureCallAsync(new Request { RequestType = RequestType.DiskEncounter, RequestMessage = new DiskEncounterMessage { EncounterId = fortData.LureInfo.EncounterId, FortId = fortData.Id, GymLatDegrees = fortData.Latitude, GymLngDegrees = fortData.Longitude, PlayerLatitude = _client.ClientSession.Player.Latitude, PlayerLongitude = _client.ClientSession.Player.Longitude }.ToByteString() }); if (response == null) { return(new MethodResult()); } DiskEncounterResponse eResponse = DiskEncounterResponse.Parser.ParseFrom(response); switch (eResponse.Result) { case DiskEncounterResponse.Types.Result.Success: if (LastedEncountersIds.Count > 30) { LastedEncountersIds.Clear(); } LastedEncountersIds.Add(eResponse.PokemonData.Id); CatchPokemonResponse catchPokemonResponse = null; int attemptCount = 1; var berryUsed = false; if (eResponse.PokemonData == null || eResponse.PokemonData.PokemonId == PokemonId.Missingno) { return(new MethodResult()); } do { if (!CatchDisabled) { if (RemainingPokeballs() < 1) { LogCaller(new LoggerEventArgs("You don't have any pokeball catching (Lure) pokemon will be disabled during " + UserSettings.DisableCatchDelay.ToString(CultureInfo.InvariantCulture) + " minutes.", LoggerTypes.Info)); CatchDisabled = true; TimeAutoCatch = DateTime.Now.AddMinutes(UserSettings.DisableCatchDelay); return(new MethodResult()); } } else { return(new MethodResult()); } //Uses lowest capture probability float probability = eResponse.CaptureProbability.CaptureProbability_[0]; ItemId pokeBall = GetBestBall(eResponse.PokemonData); if (UserSettings.UseBerries) { bool isLowProbability = probability < 0.35; bool isHighCp = eResponse.PokemonData.Cp > 700; bool isHighPerfection = CalculateIVPerfection(eResponse.PokemonData) > 90; if (!berryUsed) { if ((isLowProbability && isHighCp) || isHighPerfection) { await UseBerry(fortData.LureInfo.EncounterId, fortData.Id, ItemId.ItemRazzBerry); berryUsed = true; } else { bool isHighProbability = probability > 0.65; var catchSettings = UserSettings.CatchSettings.FirstOrDefault(x => x.Id == eResponse.PokemonData.PokemonId); if (isHighProbability && catchSettings.UsePinap) { await UseBerry(fortData.LureInfo.EncounterId, fortData.Id, ItemId.ItemPinapBerry); berryUsed = true; } else if (new Random().Next(0, 100) < 50) { // IF we dont use razz neither use pinap, then we will use nanab randomly the 50% of times. await UseBerry(fortData.LureInfo.EncounterId, fortData.Id, ItemId.ItemNanabBerry); berryUsed = true; } } } } double reticuleSize = 1.95; bool hitInsideReticule = true; //Humanization if (UserSettings.EnableHumanization) { reticuleSize = (double)_rand.Next(10, 195) / 100; hitInsideReticule = HitInsideReticle(); } //End humanization var arPlusValues = new ARPlusEncounterValues(); if (UserSettings.GetArBonus) { LogCaller(new LoggerEventArgs("Using AR Bonus Values", LoggerTypes.Debug)); arPlusValues.Awareness = (float)UserSettings.ARBonusAwareness; arPlusValues.Proximity = (float)UserSettings.ARBonusProximity; arPlusValues.PokemonFrightened = false; } if (!_client.LoggedIn) { MethodResult result = await AcLogin(); if (!result.Success) { return(result); } } var catchresponse = await _client.ClientSession.RpcClient.SendRemoteProcedureCallAsync(new Request { RequestType = RequestType.CatchPokemon, RequestMessage = new CatchPokemonMessage { ArPlusValues = arPlusValues, EncounterId = fortData.LureInfo.EncounterId, HitPokemon = hitInsideReticule, NormalizedHitPosition = 1, NormalizedReticleSize = reticuleSize, Pokeball = pokeBall, SpawnPointId = fortData.Id, SpinModifier = 1 }.ToByteString() }); if (catchresponse == null) { return(new MethodResult()); } catchPokemonResponse = CatchPokemonResponse.Parser.ParseFrom(catchresponse); string pokemon = String.Format("Name: {0}, CP: {1}, IV: {2:0.00}%", fortData.LureInfo.ActivePokemonId, eResponse.PokemonData.Cp, CalculateIVPerfection(eResponse.PokemonData)); string pokeBallName = pokeBall.ToString().Replace("Item", ""); switch (catchPokemonResponse.Status) { case CatchPokemonResponse.Types.CatchStatus.CatchError: LogCaller(new LoggerEventArgs(String.Format("Unknown Error. {0}. Attempt #{1}. Status: {2}", pokemon, attemptCount, catchPokemonResponse.Status), LoggerTypes.Warning)); continue; case CatchPokemonResponse.Types.CatchStatus.CatchEscape: //If we get this response, means we're good _fleeingPokemonResponses = 0; _potentialPokemonBan = false; if (AccountState == AccountState.SoftBan || AccountState == AccountState.HashIssues) { AccountState = AccountState.Good; LogCaller(new LoggerEventArgs("Pokemon ban was lifted", LoggerTypes.Info)); } LogCaller(new LoggerEventArgs(String.Format("Escaped ball. {0}. Attempt #{1}. Ball: {2}", pokemon, attemptCount, pokeBallName), LoggerTypes.PokemonEscape)); continue; case CatchPokemonResponse.Types.CatchStatus.CatchFlee: ++_fleeingPokemonResponses; LogCaller(new LoggerEventArgs(String.Format("Pokemon fled. {0}. Attempt #{1}. Ball: {2}", pokemon, attemptCount, pokeBallName), LoggerTypes.PokemonFlee)); continue; case CatchPokemonResponse.Types.CatchStatus.CatchMissed: LogCaller(new LoggerEventArgs(String.Format("Missed. {0}. Attempt #{1}. Status: {2}", pokemon, attemptCount, catchPokemonResponse.Status), LoggerTypes.Warning)); continue; case CatchPokemonResponse.Types.CatchStatus.CatchSuccess: int expGained = catchPokemonResponse.CaptureAward.Xp.Sum(); int candyGained = catchPokemonResponse.CaptureAward.Candy.Sum(); Tracker.AddValues(1, 0); ExpIncrease(expGained); //_expGained += expGained; fortData.LureInfo = null; LogCaller(new LoggerEventArgs(String.Format("[Lured] Pokemon Caught. {0}. Exp {1}. Candy {2}. Attempt #{3}. Ball: {4}", pokemon, expGained, candyGained, attemptCount, pokeBallName), LoggerTypes.Success)); //Auto favorit shiny if (UserSettings.AutoFavoritShiny && eResponse.PokemonData.PokemonDisplay.Shiny) { LogCaller(new LoggerEventArgs(String.Format("[{0}] Pokemon shiny. Auto favorit this pokemon.", eResponse.PokemonData.PokemonId.ToString()), LoggerTypes.Info)); await FavoritePokemon(new List <PokemonData> { eResponse.PokemonData }, true); await Task.Delay(CalculateDelay(UserSettings.DelayBetweenPlayerActions, UserSettings.PlayerActionDelayRandom)); } //Pokemon.Add(eResponse.PokemonData); UpdateInventory(InventoryRefresh.Pokemon); return(new MethodResult { Message = "Pokemon caught", Success = true }); } ++attemptCount; await Task.Delay(CalculateDelay(UserSettings.DelayBetweenPlayerActions, UserSettings.PlayerActionDelayRandom)); } while (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchMissed || catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape); return(new MethodResult()); case DiskEncounterResponse.Types.Result.EncounterAlreadyFinished: break; case DiskEncounterResponse.Types.Result.NotAvailable: break; case DiskEncounterResponse.Types.Result.NotInRange: break; case DiskEncounterResponse.Types.Result.PokemonInventoryFull: break; case DiskEncounterResponse.Types.Result.Unknown: break; } if (LastedEncountersIds.Count > 30) { LastedEncountersIds.Clear(); } LastedEncountersIds.Add(fortData.LureInfo.EncounterId); LogCaller(new LoggerEventArgs(String.Format("Faill cath lure on pokestop {0}. {1}.", fortData.Id, eResponse.Result), LoggerTypes.Warning)); return(new MethodResult()); }
private async Task <MethodResult> CatchPokemon(EncounterResponse eResponse, MapPokemon mapPokemon) { try { CatchPokemonResponse catchPokemonResponse = null; int attemptCount = 1; do { //Uses lowest capture probability float probability = eResponse.CaptureProbability.CaptureProbability_[0]; ItemId pokeBall = GetBestBall(eResponse.WildPokemon.PokemonData); if (pokeBall == ItemId.ItemUnknown) { LogCaller(new LoggerEventArgs("No pokeballs remaining", LoggerTypes.Warning)); return(new MethodResult { Message = "No pokeballs remaining" }); } bool isLowProbability = probability < 0.40; bool isHighCp = eResponse.WildPokemon.PokemonData.Cp > 800; bool isHighPerfection = CalculateIVPerfection(eResponse.WildPokemon.PokemonData).Data > 95; if ((isLowProbability && isHighCp) || isHighPerfection) { await Task.Delay(200); await UseBerry(mapPokemon); } await Task.Delay(200); catchPokemonResponse = await _client.Encounter.CatchPokemon(mapPokemon.EncounterId, mapPokemon.SpawnPointId, pokeBall); string pokemon = String.Format("Name: {0}, CP: {1}, IV: {2:0.00}%", mapPokemon.PokemonId, eResponse.WildPokemon.PokemonData.Cp, CalculateIVPerfection(eResponse.WildPokemon.PokemonData).Data); string pokeBallName = pokeBall.ToString().Replace("Item", ""); if (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchSuccess) { int expGained = catchPokemonResponse.CaptureAward.Xp.Sum(); ExpIncrease(expGained); //_expGained += expGained; LogCaller(new LoggerEventArgs(String.Format("Caught. {0}. Exp {1}. Attempt #{2}. Ball: {3}", pokemon, expGained, attemptCount, pokeBallName), LoggerTypes.Success)); return(new MethodResult { Message = "Pokemon caught", Success = true }); } else if (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchFlee) { LogCaller(new LoggerEventArgs(String.Format("Pokemon fled. {0}. Attempt #{1}. Ball: {2}", pokemon, attemptCount, pokeBallName), LoggerTypes.PokemonFlee)); } else if (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape) { LogCaller(new LoggerEventArgs(String.Format("Escaped ball. {0}. Attempt #{1}. Ball: {2}", pokemon, attemptCount, pokeBallName), LoggerTypes.PokemonEscape)); } else { LogCaller(new LoggerEventArgs(String.Format("Unknown Error. {0}. Attempt #{1}. Status: {2}", pokemon, attemptCount, catchPokemonResponse.Status), LoggerTypes.Warning)); } ++attemptCount; await Task.Delay(500); } while (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchMissed || catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape); } catch (Exception ex) { LogCaller(new LoggerEventArgs("Failed to catch pokemon due to error", LoggerTypes.Exception, ex)); return(new MethodResult { Message = "Failed to catch pokemon" }); } return(new MethodResult { Message = "Failed to catch pokemon", Success = true }); }
private async Task <MethodResult> CatchPokemon(FortData fortData) { try { DiskEncounterResponse eResponse = await _client.Encounter.EncounterLurePokemon(fortData.LureInfo.EncounterId, fortData.Id); if (eResponse.Result == DiskEncounterResponse.Types.Result.PokemonInventoryFull) { LogCaller(new LoggerEventArgs("Encounter failed. Pokemon inventory full", LoggerTypes.Warning)); return(new MethodResult { Message = "Encounter failed. Pokemon inventory full" }); } else if (eResponse.Result != DiskEncounterResponse.Types.Result.Success) { if (eResponse.Result == DiskEncounterResponse.Types.Result.NotAvailable) { //Ignore return(new MethodResult { Message = "Encounter not available" }); } LogCaller(new LoggerEventArgs(String.Format("Lured encounter failed with response {0}", eResponse.Result), LoggerTypes.Warning)); return(new MethodResult { Message = "Encounter failed" }); } CatchPokemonResponse catchPokemonResponse = null; int attemptCount = 1; do { //Uses lowest capture probability float probability = eResponse.CaptureProbability.CaptureProbability_[0]; ItemId pokeBall = GetBestBall(eResponse.PokemonData); if (pokeBall == ItemId.ItemUnknown) { LogCaller(new LoggerEventArgs("No pokeballs remaining", LoggerTypes.Warning)); return(new MethodResult { Message = "No pokeballs remaining" }); } bool isLowProbability = probability < 0.35; bool isHighCp = eResponse.PokemonData.Cp > 700; bool isHighPerfection = CalculateIVPerfection(eResponse.PokemonData).Data > 90; if ((isLowProbability && isHighCp) || isHighPerfection) { await UseBerry(fortData.LureInfo.EncounterId, fortData.Id); } catchPokemonResponse = await _client.Encounter.CatchPokemon(fortData.LureInfo.EncounterId, fortData.Id, pokeBall); string pokemon = String.Format("Name: {0}, CP: {1}, IV: {2:0.00}%", fortData.LureInfo.ActivePokemonId, eResponse.PokemonData.Cp, CalculateIVPerfection(eResponse.PokemonData).Data); if (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchSuccess) { int expGained = catchPokemonResponse.CaptureAward.Xp.Sum(); ExpIncrease(expGained); //_expGained += expGained; LogCaller(new LoggerEventArgs(String.Format("Lured Pokemon Caught. {0}. Exp {1}. Attempt #{2}", pokemon, expGained, attemptCount), LoggerTypes.Success)); return(new MethodResult { Message = "Pokemon caught", Success = true }); } else if (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchFlee) { LogCaller(new LoggerEventArgs(String.Format("Pokemon fled. {0}. Attempt #{1}", pokemon, attemptCount), LoggerTypes.PokemonFlee)); } else if (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape) { LogCaller(new LoggerEventArgs(String.Format("Escaped ball. {0}. Attempt #{1}.", pokemon, attemptCount), LoggerTypes.PokemonEscape)); } else { LogCaller(new LoggerEventArgs(String.Format("Unknown Error. {0}. Attempt #{1}. Status: {2}", pokemon, attemptCount, catchPokemonResponse.Status), LoggerTypes.Warning)); } ++attemptCount; await Task.Delay(1000); } while (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchMissed || catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape); } catch (Exception ex) { LogCaller(new LoggerEventArgs("Failed to catch lured pokemon due to error", LoggerTypes.Exception, ex)); return(new MethodResult { Message = "Failed to catch lured pokemon" }); } return(new MethodResult { Message = "Failed to catch lured pokemon", Success = true }); }
//Catch encountered pokemon private async Task <MethodResult> CatchPokemon(EncounterResponse eResponse, MapPokemon mapPokemon) { try { CatchPokemonResponse catchPokemonResponse = null; int attemptCount = 1; do { //Uses lowest capture probability float probability = eResponse.CaptureProbability.CaptureProbability_[0]; ItemId pokeBall = await GetBestBall(eResponse.WildPokemon.PokemonData); if (pokeBall == ItemId.ItemUnknown) { LogCaller(new LoggerEventArgs("No pokeballs remaining (encounter)", LoggerTypes.Warning)); return(new MethodResult { Message = "No pokeballs remaining" }); } bool isLowProbability = probability < 0.40; bool isHighCp = eResponse.WildPokemon.PokemonData.Cp > 800; bool isHighPerfection = CalculateIVPerfection(eResponse.WildPokemon.PokemonData).Data > 95; if ((isLowProbability && isHighCp) || isHighPerfection) { await Task.Delay(CalculateDelay(UserSettings.DelayBetweenPlayerActions, UserSettings.PlayerActionDelayRandom)); await UseBerry(mapPokemon); } await Task.Delay(CalculateDelay(UserSettings.DelayBetweenPlayerActions, UserSettings.PlayerActionDelayRandom)); double reticuleSize = 1.95; int hitInsideReticule = 1; //Humanization if (UserSettings.EnableHumanization) { reticuleSize = (double)_rand.Next(10, 195) / 100; hitInsideReticule = HitInsideReticle(); } catchPokemonResponse = await _client.Encounter.CatchPokemon(mapPokemon.EncounterId, mapPokemon.SpawnPointId, pokeBall, reticuleSize, 1, hitInsideReticule); string pokemon = String.Format("Name: {0}, CP: {1}, IV: {2:0.00}%", mapPokemon.PokemonId, eResponse.WildPokemon.PokemonData.Cp, CalculateIVPerfection(eResponse.WildPokemon.PokemonData).Data); string pokeBallName = pokeBall.ToString().Replace("Item", ""); if (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchSuccess) { //Reset data _fleeingPokemonResponses = 0; ++PokemonCaught; _potentialPokemonBan = false; int expGained = catchPokemonResponse.CaptureAward.Xp.Sum(); ExpIncrease(expGained); //_expGained += expGained; LogCaller(new LoggerEventArgs(String.Format("Caught. {0}. Exp {1}. Attempt #{2}. Ball: {3}", pokemon, expGained, attemptCount, pokeBallName), LoggerTypes.Success)); return(new MethodResult { Message = "Pokemon caught", Success = true }); } else if (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchFlee) { ++_fleeingPokemonResponses; LogCaller(new LoggerEventArgs(String.Format("Pokemon fled. {0}. Attempt #{1}. Ball: {2}", pokemon, attemptCount, pokeBallName), LoggerTypes.PokemonFlee)); } else if (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape) { //If we get this response, means we're good _fleeingPokemonResponses = 0; _potentialPokemonBan = false; if (AccountState == Enums.AccountState.PokemonBanAndPokestopBanTemp || AccountState == Enums.AccountState.PokemonBanTemp) { if (AccountState == Enums.AccountState.PokemonBanAndPokestopBanTemp) { AccountState = Enums.AccountState.PokestopBanTemp; } else { AccountState = Enums.AccountState.Good; } LogCaller(new LoggerEventArgs("Pokemon ban was lifted", LoggerTypes.Info)); } LogCaller(new LoggerEventArgs(String.Format("Escaped ball. {0}. Attempt #{1}. Ball: {2}", pokemon, attemptCount, pokeBallName), LoggerTypes.PokemonEscape)); } else { LogCaller(new LoggerEventArgs(String.Format("Unknown Error. {0}. Attempt #{1}. Status: {2}", pokemon, attemptCount, catchPokemonResponse.Status), LoggerTypes.Warning)); } ++attemptCount; await Task.Delay(CalculateDelay(UserSettings.DelayBetweenPlayerActions, UserSettings.PlayerActionDelayRandom)); } while (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchMissed || catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape); } catch (Exception ex) { LogCaller(new LoggerEventArgs("Failed to catch pokemon due to error", LoggerTypes.Exception, ex)); return(new MethodResult { Message = "Failed to catch pokemon" }); } return(new MethodResult { Message = "Failed to catch pokemon", Success = true }); }
/// <summary> /// Provides a safe way to invoke the <see cref="CatchPokemonReceived" /> event. /// </summary> /// <param name="value"></param> public void RaiseCatchPokemonReceived(CatchPokemonResponse value) => CatchPokemonReceived?.Invoke(this, value);
public static async Task Execute(ISession session, CancellationToken cancellationToken, dynamic encounter, MapPokemon pokemon, FortData currentFortData = null, ulong encounterId = 0, bool sessionAllowTransfer = true) { AmountOfBerries = 0; cancellationToken.ThrowIfCancellationRequested(); // If the encounter is null nothing will work below, so exit now if (encounter == null) { return; } // Exit if user defined max limits reached if (CatchThresholdExceeds(session, cancellationToken)) { return; } float probability = encounter.CaptureProbability?.CaptureProbability_[0]; // Check for pokeballs before proceeding var pokeball = await GetBestBall(session, encounter, probability); if (pokeball == ItemId.ItemUnknown) { return; } //Calculate CP and IV var pokemonCp = (encounter is EncounterResponse ? encounter.WildPokemon?.PokemonData?.Cp : encounter.PokemonData?.Cp); var pokemonIv = PokemonInfo.CalculatePokemonPerfection(encounter is EncounterResponse ? encounter.WildPokemon?.PokemonData : encounter?.PokemonData); // Calculate distance away var distance = LocationUtils.CalculateDistanceInMeters(session.Client.CurrentLatitude, session.Client.CurrentLongitude, encounter is EncounterResponse || encounter is IncenseEncounterResponse ? pokemon.Latitude : currentFortData.Latitude, encounter is EncounterResponse || encounter is IncenseEncounterResponse ? pokemon.Longitude : currentFortData.Longitude); CatchPokemonResponse caughtPokemonResponse = null; var lastThrow = CatchPokemonResponse.Types.CatchStatus.CatchSuccess; // Initializing lastThrow var attemptCounter = 1; do { if ((session.LogicSettings.MaxPokeballsPerPokemon > 0 && attemptCounter > session.LogicSettings.MaxPokeballsPerPokemon)) { break; } pokeball = await GetBestBall(session, encounter, probability); if (pokeball == ItemId.ItemUnknown) { session.EventDispatcher.Send(new NoPokeballEvent { Id = encounter is EncounterResponse ? pokemon.PokemonId : encounter?.PokemonData.PokemonId, Cp = (encounter is EncounterResponse ? encounter.WildPokemon?.PokemonData?.Cp : encounter?.PokemonData?.Cp) ?? 0 }); return; } // Determine whether to use berries or not if (((session.LogicSettings.UseBerriesOperator.ToLower().Equals("and") && pokemonIv >= session.LogicSettings.UseBerriesMinIv && pokemonCp >= session.LogicSettings.UseBerriesMinCp && probability < session.LogicSettings.UseBerriesBelowCatchProbability) || (session.LogicSettings.UseBerriesOperator.ToLower().Equals("or") && ( pokemonIv >= session.LogicSettings.UseBerriesMinIv || pokemonCp >= session.LogicSettings.UseBerriesMinCp || probability < session.LogicSettings.UseBerriesBelowCatchProbability))) && lastThrow != CatchPokemonResponse.Types.CatchStatus.CatchMissed) // if last throw is a miss, no double berry { AmountOfBerries++; if (AmountOfBerries <= session.LogicSettings.MaxBerriesToUsePerPokemon) { await UseBerry(session, encounter is EncounterResponse || encounter is IncenseEncounterResponse ?pokemon.EncounterId : encounterId, encounter is EncounterResponse || encounter is IncenseEncounterResponse ?pokemon.SpawnPointId : currentFortData?.Id); } } bool hitPokemon = true; //default to excellent throw var normalizedRecticleSize = 1.95; //default spin var spinModifier = 1.0; //Humanized throws if (session.LogicSettings.EnableHumanizedThrows) { //thresholds: https://gist.github.com/anonymous/077d6dea82d58b8febde54ae9729b1bf var spinTxt = "Curve"; var hitTxt = "Excellent"; if (pokemonCp > session.LogicSettings.ForceExcellentThrowOverCp || pokemonIv > session.LogicSettings.ForceExcellentThrowOverIv) { normalizedRecticleSize = Random.NextDouble() * (1.95 - 1.7) + 1.7; } else if (pokemonCp >= session.LogicSettings.ForceGreatThrowOverCp || pokemonIv >= session.LogicSettings.ForceGreatThrowOverIv) { normalizedRecticleSize = Random.NextDouble() * (1.95 - 1.3) + 1.3; hitTxt = "Great"; } else { var regularThrow = 100 - (session.LogicSettings.ExcellentThrowChance + session.LogicSettings.GreatThrowChance + session.LogicSettings.NiceThrowChance); var rnd = Random.Next(1, 101); if (rnd <= regularThrow) { normalizedRecticleSize = Random.NextDouble() * (1 - 0.1) + 0.1; hitTxt = "Ordinary"; } else if (rnd <= regularThrow + session.LogicSettings.NiceThrowChance) { normalizedRecticleSize = Random.NextDouble() * (1.3 - 1) + 1; hitTxt = "Nice"; } else if (rnd <= regularThrow + session.LogicSettings.NiceThrowChance + session.LogicSettings.GreatThrowChance) { normalizedRecticleSize = Random.NextDouble() * (1.7 - 1.3) + 1.3; hitTxt = "Great"; } if (Random.NextDouble() * 100 > session.LogicSettings.CurveThrowChance) { spinModifier = 0.0; spinTxt = "Straight"; } } //round to 2 decimals normalizedRecticleSize = Math.Round(normalizedRecticleSize, 2); // Missed throw check int missChance = Random.Next(1, 101); if (missChance <= session.LogicSettings.ThrowMissPercentage && session.LogicSettings.EnableMissedThrows) { hitPokemon = false; } Logger.Write($"(Threw ball) {hitTxt} throw, {spinTxt}-ball, HitPokemon = {hitPokemon}...", LogLevel.Debug); } caughtPokemonResponse = await session.Client.Encounter.CatchPokemon( encounter is EncounterResponse || encounter is IncenseEncounterResponse ?pokemon.EncounterId : encounterId, encounter is EncounterResponse || encounter is IncenseEncounterResponse ?pokemon.SpawnPointId : currentFortData.Id, pokeball, normalizedRecticleSize, spinModifier, hitPokemon); var lat = encounter is EncounterResponse || encounter is IncenseEncounterResponse ? pokemon.Latitude : currentFortData.Latitude; var lng = encounter is EncounterResponse || encounter is IncenseEncounterResponse ? pokemon.Longitude : currentFortData.Longitude; var evt = new PokemonCaptureEvent() { Status = caughtPokemonResponse.Status, Latitude = lat, Longitude = lng }; lastThrow = caughtPokemonResponse.Status; // sets lastThrow status if (caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchSuccess) { var totalExp = 0; foreach (var xp in caughtPokemonResponse.CaptureAward.Xp) { totalExp += xp; } var profile = await session.Client.Player.GetPlayer(); evt.Exp = totalExp; evt.Stardust = profile.PlayerData.Currencies.ToArray()[1].Amount; evt.UniqueId = caughtPokemonResponse.CapturedPokemonId; var pokemonSettings = await session.Inventory.GetPokemonSettings(); var pokemonFamilies = await session.Inventory.GetPokemonFamilies(); var setting = pokemonSettings.FirstOrDefault(q => pokemon != null && q.PokemonId == pokemon.PokemonId); var family = pokemonFamilies.FirstOrDefault(q => setting != null && q.FamilyId == setting.FamilyId); if (family != null) { family.Candy_ += caughtPokemonResponse.CaptureAward.Candy.Sum(); evt.FamilyCandies = family.Candy_; } else { evt.FamilyCandies = caughtPokemonResponse.CaptureAward.Candy.Sum(); } if (session.LogicSettings.UseCatchLimit) { session.Stats.PokemonTimestamps.Add(DateTime.Now.Ticks); UpdateTimeStampsPokemon?.Invoke(); Logger.Write($"(CATCH LIMIT) {session.Stats.PokemonTimestamps.Count}/{session.LogicSettings.CatchPokemonLimit}", LogLevel.Info, ConsoleColor.Yellow); } } evt.CatchType = encounter is EncounterResponse ? session.Translation.GetTranslation(TranslationString.CatchTypeNormal) : encounter is DiskEncounterResponse ? session.Translation.GetTranslation(TranslationString.CatchTypeLure) : session.Translation.GetTranslation(TranslationString.CatchTypeIncense); evt.CatchTypeText = encounter is EncounterResponse ? "normal" : encounter is DiskEncounterResponse ? "lure" : "incense"; evt.Id = encounter is EncounterResponse ? pokemon.PokemonId : encounter?.PokemonData.PokemonId; evt.EncounterId = encounter is EncounterResponse || encounter is IncenseEncounterResponse ? pokemon.EncounterId : encounterId; evt.Move1 = PokemonInfo.GetPokemonMove1(encounter is EncounterResponse ? encounter.WildPokemon?.PokemonData : encounter?.PokemonData); evt.Move2 = PokemonInfo.GetPokemonMove2(encounter is EncounterResponse ? encounter.WildPokemon?.PokemonData : encounter?.PokemonData); evt.Expires = pokemon?.ExpirationTimestampMs ?? 0; evt.SpawnPointId = encounter is EncounterResponse || encounter is IncenseEncounterResponse ? pokemon.SpawnPointId : currentFortData?.Id; evt.Level = PokemonInfo.GetLevel(encounter is EncounterResponse ? encounter.WildPokemon?.PokemonData : encounter?.PokemonData); evt.Cp = encounter is EncounterResponse ? encounter.WildPokemon?.PokemonData?.Cp : encounter?.PokemonData?.Cp ?? 0; evt.MaxCp = PokemonInfo.CalculateMaxCp(encounter is EncounterResponse ? encounter.WildPokemon?.PokemonData : encounter?.PokemonData); evt.Perfection = Math.Round( PokemonInfo.CalculatePokemonPerfection(encounter is EncounterResponse ? encounter.WildPokemon?.PokemonData : encounter?.PokemonData)); evt.Probability = Math.Round(probability * 100, 2); evt.Distance = distance; evt.Pokeball = pokeball; evt.Attempt = attemptCounter; await session.Inventory.RefreshCachedInventory(); evt.BallAmount = await session.Inventory.GetItemAmountByType(pokeball); evt.Rarity = PokemonGradeHelper.GetPokemonGrade(evt.Id).ToString(); session.EventDispatcher.Send(evt); attemptCounter++; DelayingUtils.Delay(session.LogicSettings.DelayBetweenPlayerActions, 0); } while (caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchMissed || caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape); if (session.LogicSettings.TransferDuplicatePokemonOnCapture && session.LogicSettings.TransferDuplicatePokemon && sessionAllowTransfer && caughtPokemonResponse != null && caughtPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchSuccess) { if (session.LogicSettings.UseNearActionRandom) { await HumanRandomActionTask.TransferRandom(session, cancellationToken); } else { await TransferDuplicatePokemonTask.Execute(session, cancellationToken); } } }
//Catch encountered pokemon private async Task <MethodResult> CatchPokemon(dynamic eResponse, MapPokemon mapPokemon) { PokemonData _encounteredPokemon = null; long _unixTimeStamp = 0; ulong _encounterId = 0; string _spawnPointId = null; string _pokemonType = null; // Calling from CatchNormalPokemon if (eResponse is EncounterResponse && (eResponse?.Status == EncounterResponse.Types.Status.EncounterSuccess)) { _encounteredPokemon = eResponse.WildPokemon?.PokemonData; _unixTimeStamp = eResponse.WildPokemon?.LastModifiedTimestampMs + eResponse.WildPokemon?.TimeTillHiddenMs; _spawnPointId = eResponse.WildPokemon?.SpawnPointId; _encounterId = eResponse.WildPokemon?.EncounterId; _pokemonType = "Normal"; } // Calling from CatchIncensePokemon else if (eResponse is IncenseEncounterResponse && (eResponse?.Result == IncenseEncounterResponse.Types.Result.IncenseEncounterSuccess)) { _encounteredPokemon = eResponse?.PokemonData; _unixTimeStamp = mapPokemon.ExpirationTimestampMs; _spawnPointId = mapPokemon.SpawnPointId; _encounterId = mapPokemon.EncounterId; _pokemonType = "Incense"; } CatchPokemonResponse catchPokemonResponse = null; int attemptCount = 1; do { if (mapPokemon == null) { return(new MethodResult()); } //Uses lowest capture probability float probability = eResponse.CaptureProbability.CaptureProbability_[0]; ItemId pokeBall = GetBestBall(_encounteredPokemon); if (pokeBall == ItemId.ItemUnknown) { LogCaller(new LoggerEventArgs("No pokeballs remaining (encounter)", LoggerTypes.Warning)); return(new MethodResult { Message = "No pokeballs remaining" }); } bool isLowProbability = probability < 0.40; bool isHighCp = _encounteredPokemon.Cp > 800; bool isHighPerfection = CalculateIVPerfection(_encounteredPokemon) > 95; if (UserSettings.UseBerries) { if ((isLowProbability && isHighCp) || isHighPerfection) { await Task.Delay(CalculateDelay(UserSettings.DelayBetweenPlayerActions, UserSettings.PlayerActionDelayRandom)); await UseBerry(mapPokemon, ItemId.ItemRazzBerry); } else { bool isHighProbability = probability > 0.65; if (isHighProbability) { await UseBerry(mapPokemon, ItemId.ItemPinapBerry); } else if (new Random().Next(0, 100) < 50) { // IF we dont use razz neither use pinap, then we will use nanab randomly the 50% of times. await UseBerry(mapPokemon, ItemId.ItemNanabBerry); } } } await Task.Delay(CalculateDelay(UserSettings.DelayBetweenPlayerActions, UserSettings.PlayerActionDelayRandom)); double reticuleSize = 1.95; bool hitInsideReticule = true; //Humanization if (UserSettings.EnableHumanization) { reticuleSize = (double)_rand.Next(10, 195) / 100; hitInsideReticule = HitInsideReticle(); } var arPlusValues = new ARPlusEncounterValues(); if (UserSettings.GetArBonus) { LogCaller(new LoggerEventArgs("Using AR Bonus Values", LoggerTypes.Debug)); arPlusValues.Awareness = (float)UserSettings.ARBonusAwareness; arPlusValues.Proximity = (float)UserSettings.ARBonusProximity; arPlusValues.PokemonFrightened = false; } var catchresponse = await _client.ClientSession.RpcClient.SendRemoteProcedureCallAsync(new Request { RequestType = RequestType.CatchPokemon, RequestMessage = new CatchPokemonMessage { ArPlusValues = arPlusValues, EncounterId = _encounterId, HitPokemon = hitInsideReticule, NormalizedHitPosition = 1, NormalizedReticleSize = reticuleSize, Pokeball = pokeBall, SpawnPointId = _spawnPointId, SpinModifier = 1 }.ToByteString() }); if (catchresponse == null) { return(new MethodResult()); } catchPokemonResponse = CatchPokemonResponse.Parser.ParseFrom(catchresponse); string pokemon = String.Format("Name: {0}, CP: {1}, IV: {2:0.00}%", mapPokemon.PokemonId, _encounteredPokemon.Cp, CalculateIVPerfection(_encounteredPokemon)); string pokeBallName = pokeBall.ToString().Replace("Item", ""); switch (catchPokemonResponse.Status) { case CatchPokemonResponse.Types.CatchStatus.CatchError: LogCaller(new LoggerEventArgs(String.Format("Unknown Error. {0}. Attempt #{1}. Status: {2}", pokemon, attemptCount, catchPokemonResponse.Status), LoggerTypes.Warning)); continue; case CatchPokemonResponse.Types.CatchStatus.CatchEscape: //If we get this response, means we're good _fleeingPokemonResponses = 0; _potentialPokemonBan = false; if (AccountState == Enums.AccountState.SoftBan) { AccountState = Enums.AccountState.Good; LogCaller(new LoggerEventArgs("Pokemon ban was lifted", LoggerTypes.Info)); } LogCaller(new LoggerEventArgs(String.Format("Escaped ball. {0}. Attempt #{1}. Ball: {2}", pokemon, attemptCount, pokeBallName), LoggerTypes.PokemonEscape)); continue; case CatchPokemonResponse.Types.CatchStatus.CatchFlee: ++_fleeingPokemonResponses; LogCaller(new LoggerEventArgs(String.Format("Pokemon fled. {0}. Attempt #{1}. Ball: {2}", pokemon, attemptCount, pokeBallName), LoggerTypes.PokemonFlee)); continue; case CatchPokemonResponse.Types.CatchStatus.CatchMissed: LogCaller(new LoggerEventArgs(String.Format("Missed. {0}. Attempt #{1}. Status: {2}", pokemon, attemptCount, catchPokemonResponse.Status), LoggerTypes.Warning)); continue; case CatchPokemonResponse.Types.CatchStatus.CatchSuccess: //Reset data _fleeingPokemonResponses = 0; Tracker.AddValues(1, 0); _potentialPokemonBan = false; int expGained = catchPokemonResponse.CaptureAward.Xp.Sum(); int candyGained = catchPokemonResponse.CaptureAward.Candy.Sum(); ExpIncrease(expGained); //_expGained += expGained; //NOTE: To be sure that we don't repeat this encounter, we will delete it from the cell var cell = _client.ClientSession.Map.Cells.FirstOrDefault(x => x.CatchablePokemons.FirstOrDefault(y => y.EncounterId == mapPokemon.EncounterId) != null); if (cell != null) { var mapPokemonFound = cell.CatchablePokemons.FirstOrDefault(y => y.EncounterId == mapPokemon.EncounterId); if (mapPokemonFound != null) { cell.CatchablePokemons.Remove(mapPokemonFound); } } LogCaller(new LoggerEventArgs(String.Format("[{0}] Pokemon Caught. {1}. Exp {2}. Candy: {3}. Attempt #{4}. Ball: {5}", _pokemonType, pokemon, expGained, candyGained, attemptCount, pokeBallName), LoggerTypes.Success)); //Pokemon.Add(_encounteredPokemon); UpdateInventory(InventoryRefresh.Pokemon); return(new MethodResult { Message = "Pokemon caught", Success = true }); } ++attemptCount; await Task.Delay(CalculateDelay(UserSettings.DelayBetweenPlayerActions, UserSettings.PlayerActionDelayRandom)); } while (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchMissed || catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape); return(new MethodResult()); }
//Catch lured pokemon private async Task <MethodResult> CatchPokemon(FortData fortData) { var response = await _client.ClientSession.RpcClient.SendRemoteProcedureCallAsync(new Request { RequestType = RequestType.DiskEncounter, RequestMessage = new DiskEncounterMessage { EncounterId = fortData.LureInfo.EncounterId, FortId = fortData.Id, GymLatDegrees = fortData.Latitude, GymLngDegrees = fortData.Longitude, PlayerLatitude = _client.ClientSession.Player.Latitude, PlayerLongitude = _client.ClientSession.Player.Longitude }.ToByteString() }); if (response == null) { return(new MethodResult()); } DiskEncounterResponse eResponse = DiskEncounterResponse.Parser.ParseFrom(response); switch (eResponse.Result) { case DiskEncounterResponse.Types.Result.Success: CatchPokemonResponse catchPokemonResponse = null; int attemptCount = 1; var berryUsed = false; do { //Uses lowest capture probability float probability = eResponse.CaptureProbability.CaptureProbability_[0]; ItemId pokeBall = GetBestBall(eResponse.PokemonData); if (pokeBall == ItemId.ItemUnknown) { LogCaller(new LoggerEventArgs("No pokeballs remaining (lure)", LoggerTypes.Warning)); return(new MethodResult { Message = "No pokeballs remaining" }); } if (UserSettings.UseBerries) { bool isLowProbability = probability < 0.35; bool isHighCp = eResponse.PokemonData.Cp > 700; bool isHighPerfection = CalculateIVPerfection(eResponse.PokemonData) > 90; if (!berryUsed) { if ((isLowProbability && isHighCp) || isHighPerfection) { await UseBerry(fortData.LureInfo.EncounterId, fortData.Id, ItemId.ItemRazzBerry); berryUsed = true; } else { bool isHighProbability = probability > 0.65; var catchSettings = UserSettings.CatchSettings.FirstOrDefault(x => x.Id == eResponse.PokemonData.PokemonId); var usePinap = catchSettings != null && catchSettings.UsePinap; if (isHighProbability && usePinap) { await UseBerry(fortData.LureInfo.EncounterId, fortData.Id, ItemId.ItemPinapBerry); berryUsed = true; } else if (new Random().Next(0, 100) < 50) { // IF we dont use razz neither use pinap, then we will use nanab randomly the 50% of times. await UseBerry(fortData.LureInfo.EncounterId, fortData.Id, ItemId.ItemNanabBerry); berryUsed = true; } } } } double reticuleSize = 1.95; bool hitInsideReticule = true; //Humanization if (UserSettings.EnableHumanization) { reticuleSize = (double)_rand.Next(10, 195) / 100; hitInsideReticule = HitInsideReticle(); } //End humanization var arPlusValues = new ARPlusEncounterValues(); if (UserSettings.GetArBonus) { LogCaller(new LoggerEventArgs("Using AR Bonus Values", LoggerTypes.Debug)); arPlusValues.Awareness = (float)UserSettings.ARBonusAwareness; arPlusValues.Proximity = (float)UserSettings.ARBonusProximity; arPlusValues.PokemonFrightened = false; } var catchresponse = await _client.ClientSession.RpcClient.SendRemoteProcedureCallAsync(new Request { RequestType = RequestType.CatchPokemon, RequestMessage = new CatchPokemonMessage { ArPlusValues = arPlusValues, EncounterId = fortData.LureInfo.EncounterId, HitPokemon = hitInsideReticule, NormalizedHitPosition = 1, NormalizedReticleSize = reticuleSize, Pokeball = pokeBall, SpawnPointId = fortData.Id, SpinModifier = 1 }.ToByteString() }); if (catchresponse == null) { return(new MethodResult()); } catchPokemonResponse = CatchPokemonResponse.Parser.ParseFrom(catchresponse); string pokemon = String.Format("Name: {0}, CP: {1}, IV: {2:0.00}%", fortData.LureInfo.ActivePokemonId, eResponse.PokemonData.Cp, CalculateIVPerfection(eResponse.PokemonData)); string pokeBallName = pokeBall.ToString().Replace("Item", ""); switch (catchPokemonResponse.Status) { case CatchPokemonResponse.Types.CatchStatus.CatchError: LogCaller(new LoggerEventArgs(String.Format("Unknown Error. {0}. Attempt #{1}. Status: {2}", pokemon, attemptCount, catchPokemonResponse.Status), LoggerTypes.Warning)); continue; case CatchPokemonResponse.Types.CatchStatus.CatchEscape: LogCaller(new LoggerEventArgs(String.Format("Escaped ball. {0}. Attempt #{1}.", pokemon, attemptCount), LoggerTypes.PokemonEscape)); berryUsed = false; continue; case CatchPokemonResponse.Types.CatchStatus.CatchFlee: LogCaller(new LoggerEventArgs(String.Format("Pokemon fled. {0}. Attempt #{1}", pokemon, attemptCount), LoggerTypes.PokemonFlee)); continue; case CatchPokemonResponse.Types.CatchStatus.CatchMissed: LogCaller(new LoggerEventArgs(String.Format("Missed. {0}. Attempt #{1}. Status: {2}", pokemon, attemptCount, catchPokemonResponse.Status), LoggerTypes.Warning)); continue; case CatchPokemonResponse.Types.CatchStatus.CatchSuccess: int expGained = catchPokemonResponse.CaptureAward.Xp.Sum(); int candyGained = catchPokemonResponse.CaptureAward.Candy.Sum(); Tracker.AddValues(1, 0); ExpIncrease(expGained); //_expGained += expGained; fortData.LureInfo = null; LogCaller(new LoggerEventArgs(String.Format("[Lured] Pokemon Caught. {0}. Exp {1}. Candy {2}. Attempt #{3}. Ball: {4}", pokemon, expGained, candyGained, attemptCount, pokeBallName), LoggerTypes.Success)); //Pokemon.Add(eResponse.PokemonData); UpdateInventory(InventoryRefresh.Pokemon); return(new MethodResult { Message = "Pokemon caught", Success = true }); } ++attemptCount; await Task.Delay(CalculateDelay(UserSettings.DelayBetweenPlayerActions, UserSettings.PlayerActionDelayRandom)); } while (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchMissed || catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape); break; case DiskEncounterResponse.Types.Result.EncounterAlreadyFinished: return(new MethodResult { Message = "Encounter not available" }); case DiskEncounterResponse.Types.Result.NotAvailable: return(new MethodResult { Message = "Encounter not available" }); case DiskEncounterResponse.Types.Result.NotInRange: LogCaller(new LoggerEventArgs(String.Format("Lured encounter failed with response {0}", eResponse.Result), LoggerTypes.Warning)); return(new MethodResult { Message = "Encounter failed" }); case DiskEncounterResponse.Types.Result.PokemonInventoryFull: LogCaller(new LoggerEventArgs("Encounter failed. Pokemon inventory full", LoggerTypes.Warning)); return(new MethodResult { Message = "Encounter failed. Pokemon inventory full" }); case DiskEncounterResponse.Types.Result.Unknown: LogCaller(new LoggerEventArgs(String.Format("Lured encounter failed with response {0}", eResponse.Result), LoggerTypes.Warning)); return(new MethodResult { Message = "Encounter failed" }); } return(new MethodResult()); }
//Catch lured pokemon private async Task <MethodResult> CatchPokemon(FortData fortData) { try { var response = await ClientSession.RpcClient.SendRemoteProcedureCallAsync(new Request { RequestType = RequestType.DiskEncounter, RequestMessage = new DiskEncounterMessage { EncounterId = fortData.LureInfo.EncounterId, FortId = fortData.Id, GymLatDegrees = fortData.Latitude, GymLngDegrees = fortData.Longitude, PlayerLatitude = ClientSession.Player.Latitude, PlayerLongitude = ClientSession.Player.Longitude }.ToByteString() }); DiskEncounterResponse eResponse = null; eResponse = DiskEncounterResponse.Parser.ParseFrom(response); if (eResponse.Result == DiskEncounterResponse.Types.Result.PokemonInventoryFull) { LogCaller(new LoggerEventArgs("Encounter failed. Pokemon inventory full", LoggerTypes.Warning)); return(new MethodResult { Message = "Encounter failed. Pokemon inventory full" }); } else if (eResponse.Result != DiskEncounterResponse.Types.Result.Success) { if (eResponse.Result == DiskEncounterResponse.Types.Result.NotAvailable) { //Ignore return(new MethodResult { Message = "Encounter not available" }); } LogCaller(new LoggerEventArgs(String.Format("Lured encounter failed with response {0}", eResponse.Result), LoggerTypes.Warning)); return(new MethodResult { Message = "Encounter failed" }); } CatchPokemonResponse catchPokemonResponse = null; int attemptCount = 1; do { //Uses lowest capture probability float probability = eResponse.CaptureProbability.CaptureProbability_[0]; ItemId pokeBall = await GetBestBall(eResponse.PokemonData); if (pokeBall == ItemId.ItemUnknown) { LogCaller(new LoggerEventArgs("No pokeballs remaining (lure)", LoggerTypes.Warning)); return(new MethodResult { Message = "No pokeballs remaining" }); } bool isLowProbability = probability < 0.35; bool isHighCp = eResponse.PokemonData.Cp > 700; bool isHighPerfection = CalculateIVPerfection(eResponse.PokemonData).Data > 90; if ((isLowProbability && isHighCp) || isHighPerfection) { await UseBerry(fortData.LureInfo.EncounterId, fortData.Id); } double reticuleSize = 1.95; bool hitInsideReticule = true; //Humanization if (UserSettings.EnableHumanization) { reticuleSize = (double)_rand.Next(10, 195) / 100; hitInsideReticule = HitInsideReticle(); } //End humanization var catchresponse = await ClientSession.RpcClient.SendRemoteProcedureCallAsync(new Request { RequestType = RequestType.CatchPokemon, RequestMessage = new CatchPokemonMessage { EncounterId = fortData.LureInfo.EncounterId, HitPokemon = hitInsideReticule, NormalizedHitPosition = 1, NormalizedReticleSize = reticuleSize, Pokeball = pokeBall, SpawnPointId = fortData.Id, SpinModifier = 1 }.ToByteString() }); catchPokemonResponse = CatchPokemonResponse.Parser.ParseFrom(catchresponse); string pokemon = String.Format("Name: {0}, CP: {1}, IV: {2:0.00}%", fortData.LureInfo.ActivePokemonId, eResponse.PokemonData.Cp, CalculateIVPerfection(eResponse.PokemonData).Data); if (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchSuccess) { int expGained = catchPokemonResponse.CaptureAward.Xp.Sum(); Tracker.AddValues(1, 0); ExpIncrease(expGained); //_expGained += expGained; LogCaller(new LoggerEventArgs(String.Format("Lured Pokemon Caught. {0}. Exp {1}. Attempt #{2}", pokemon, expGained, attemptCount), LoggerTypes.Success)); return(new MethodResult { Message = "Pokemon caught", Success = true }); } else if (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchFlee) { LogCaller(new LoggerEventArgs(String.Format("Pokemon fled. {0}. Attempt #{1}", pokemon, attemptCount), LoggerTypes.PokemonFlee)); } else if (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape) { LogCaller(new LoggerEventArgs(String.Format("Escaped ball. {0}. Attempt #{1}.", pokemon, attemptCount), LoggerTypes.PokemonEscape)); } else { LogCaller(new LoggerEventArgs(String.Format("Unknown Error. {0}. Attempt #{1}. Status: {2}", pokemon, attemptCount, catchPokemonResponse.Status), LoggerTypes.Warning)); } ++attemptCount; await Task.Delay(CalculateDelay(UserSettings.DelayBetweenPlayerActions, UserSettings.PlayerActionDelayRandom)); } while (catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchMissed || catchPokemonResponse.Status == CatchPokemonResponse.Types.CatchStatus.CatchEscape); } catch (Exception ex) { LogCaller(new LoggerEventArgs("Failed to catch lured pokemon due to error", LoggerTypes.Exception, ex)); return(new MethodResult { Message = "Failed to catch lured pokemon" }); } return(new MethodResult { Message = "Failed to catch lured pokemon", Success = true }); }