internal static bool CanTrainGym(ISession session, FortData fort, GetGymDetailsResponse gymDetails, ref IEnumerable <PokemonData> deployedPokemons) { bool isDeployed = deployedPokemons.Any(a => a.DeployedFortId == fort.Id); if (gymDetails != null && GetGymLevel(fort.GymPoints) > gymDetails.GymState.Memberships.Count && !isDeployed) // free slot should be used always but not always we know that... { return(true); } if (!session.LogicSettings.GymConfig.EnableGymTraining) { return(false); } if (fort.OwnedByTeam != session.Profile.PlayerData.Team) { return(false); } if (!session.LogicSettings.GymConfig.TrainAlreadyDefendedGym && isDeployed) { return(false); } if (GetGymLevel(fort.GymPoints) > session.LogicSettings.GymConfig.MaxGymLvlToTrain) { return(false); } if (GetGymMaxPointsOnLevel(GetGymLevel(fort.GymPoints)) - fort.GymPoints > session.LogicSettings.GymConfig.TrainGymWhenMissingMaxPoints) { return(false); } if (session.LogicSettings.GymConfig.DontAttackAfterCoinsLimitReached && deployedPokemons.Count() >= session.LogicSettings.GymConfig.CollectCoinAfterDeployed) { return(false); } return(true); }
public void LoadData(ISession session, FortData fort) { var task = session.Client.Fort.GetGymDetails(fort.Id, fort.Latitude, fort.Longitude); task.Wait(); if (task.IsCompleted && task.Result.Result == GetGymDetailsResponse.Types.Result.Success) { fort = task.Result.GymState.FortData; gymDetails = task.Result; lastCall = DateTime.UtcNow; } }
private static AttackGymResponse AttackGym(FortData gym, Client client, IEnumerable <PokemonData> pokeAttackers, ulong defenderId, int numDefenders, ulong buddyPokemonId) { var pokeAttackersIds = pokeAttackers.Select(x => x.Id); var moveSettings = GetMoveSettings(client); GetGymDetailsResponse gymDetails = null; StartGymBattleResponse resp = null; // Sometimes we get a null from startgymBattle so we try to start battle 3 times var numTries = 3; var startFailed = true; const int secondsToWait = 2; while (startFailed && numTries > 0) { RandomHelper.RandomSleep(800); gymDetails = client.Fort.GetGymDetails(gym.Id, gym.Latitude, gym.Longitude); RandomHelper.RandomSleep(800); var player = client.Player.GetPlayer(); RandomHelper.RandomSleep(secondsToWait * 1000); resp = StartGymBattle(client, gym.Id, defenderId, pokeAttackersIds); startFailed = false; if (resp == null) { Logger.Debug("(Gym) - Response to start battle was null."); startFailed = true; } else { if (resp.BattleLog == null) { Logger.Debug("(Gym) - BatlleLog to start battle was null"); startFailed = true; } } if (startFailed) { Logger.Debug($"(Gym) - Trying again after {secondsToWait} seconds"); } numTries--; } if (startFailed) { return(null); } if (resp.BattleLog.State == BattleState.Active) { Logger.ColoredConsoleWrite(gymColorLog, "(Gym) - Battle Started"); RandomHelper.RandomSleep(2000); var battleActions = new List <BattleAction>(); var lastRetrievedAction = new BattleAction(); var battleStartMs = resp.BattleLog.BattleStartTimestampMs; var attResp = client.Fort.AttackGym(gym.Id, resp.BattleId, battleActions, lastRetrievedAction); var inBattle = (attResp.Result == AttackGymResponse.Types.Result.Success); inBattle = inBattle && (attResp.BattleLog.State == BattleState.Active); var count = 1; var energy = 0; var numVictories = 0; Logger.Debug("attResp: " + attResp); while (inBattle) { var timeMs = attResp.BattleLog.ServerMs; var move1Settings = moveSettings.FirstOrDefault(x => x.MoveSettings.MovementId == attResp.ActiveAttacker.PokemonData.Move1).MoveSettings; var move2Settings = moveSettings.FirstOrDefault(x => x.MoveSettings.MovementId == attResp.ActiveAttacker.PokemonData.Move2).MoveSettings; battleActions = new List <BattleAction>(); var baseAction = new BattleAction(); baseAction.ActionStartMs = timeMs + RandomNumbers.Next(110, 170); baseAction.TargetIndex = -1; if (attResp.ActiveDefender != null) { baseAction.TargetPokemonId = attResp.ActiveDefender.PokemonData.Id; } if (attResp.ActiveAttacker.PokemonData.Stamina > 0) { baseAction.ActivePokemonId = attResp.ActiveAttacker.PokemonData.Id; } // One each ten times we try to evade attack if (RandomNumbers.Next(1, 10) == 1) { var dodgeAction = new BattleAction(); dodgeAction.ActionStartMs = baseAction.ActionStartMs; dodgeAction.TargetIndex = baseAction.TargetIndex; dodgeAction.TargetPokemonId = baseAction.TargetPokemonId; dodgeAction.ActivePokemonId = baseAction.ActivePokemonId; dodgeAction.Type = BattleActionType.ActionDodge; dodgeAction.DurationMs = 500; battleActions.Add(dodgeAction); Logger.Debug("Dodge Action Added"); baseAction.ActionStartMs = dodgeAction.ActionStartMs + dodgeAction.DurationMs; } if (energy >= Math.Abs(move2Settings.EnergyDelta)) { var specialAttack = new BattleAction(); specialAttack.ActionStartMs = baseAction.ActionStartMs; specialAttack.TargetIndex = baseAction.TargetIndex; specialAttack.TargetPokemonId = baseAction.TargetPokemonId; specialAttack.ActivePokemonId = baseAction.ActivePokemonId; specialAttack.Type = BattleActionType.ActionSpecialAttack; specialAttack.DurationMs = move2Settings.DurationMs; specialAttack.DamageWindowsStartTimestampMs = specialAttack.ActionStartMs + move2Settings.DamageWindowStartMs; specialAttack.DamageWindowsEndTimestampMs = specialAttack.ActionStartMs + move2Settings.DamageWindowEndMs; specialAttack.EnergyDelta = move2Settings.EnergyDelta; battleActions.Add(specialAttack); Logger.Debug("Special Attack Added"); baseAction.ActionStartMs = specialAttack.ActionStartMs + specialAttack.DurationMs; } else { // One each nine times we do not attack if (RandomNumbers.Next(1, 9) != 1) { var normalAttack = new BattleAction(); normalAttack.ActionStartMs = baseAction.ActionStartMs; normalAttack.TargetIndex = baseAction.TargetIndex; normalAttack.TargetPokemonId = baseAction.TargetPokemonId; normalAttack.ActivePokemonId = baseAction.ActivePokemonId; normalAttack.Type = BattleActionType.ActionAttack; normalAttack.DurationMs = baseAction.DurationMs; normalAttack.DamageWindowsStartTimestampMs = normalAttack.ActionStartMs + move1Settings.DamageWindowStartMs; normalAttack.DamageWindowsEndTimestampMs = normalAttack.ActionStartMs + move1Settings.DamageWindowEndMs; normalAttack.EnergyDelta = move1Settings.EnergyDelta; battleActions.Add(normalAttack); Logger.Debug("Normal Attack Added"); baseAction.ActionStartMs = normalAttack.ActionStartMs + normalAttack.DurationMs; } } lastRetrievedAction = new BattleAction(); //attResp.BattleLog.BattleActions.FirstOrDefault(); var str = string.Join(",", battleActions); Logger.Debug("(Gym) - battleActions: " + str); attResp = client.Fort.AttackGym(gym.Id, resp.BattleId, battleActions, lastRetrievedAction); Logger.Debug("attResp: " + attResp); inBattle = (attResp.Result == AttackGymResponse.Types.Result.Success); if (inBattle) { inBattle = (attResp.BattleLog.State == BattleState.Active); /* * if (attResp.BattleLog.State == BattleState.Victory){ * numVictories ++; * //inBattle = (numVictories < gymDetails.GymState.Memberships.Count); * if (numVictories < gymDetails.GymState.Memberships.Count){ * var next = gymDetails.GymState.Memberships[numVictories]; * resp = StartGymBattle(client, gym.Id, next.PokemonData.Id, pokeAttackersIds); * RandomHelper.RandomSleep(1000); * } * }*/ if (attResp.ActiveAttacker != null) { energy = attResp.ActiveAttacker.CurrentEnergy; var health = attResp.ActiveAttacker.CurrentHealth; var activeAttacker = attResp.ActiveAttacker.PokemonData.PokemonId; Logger.Debug($"(Gym) - Attacker: {activeAttacker} Energy={energy}, Health={health}"); } if (attResp.ActiveDefender != null) { var energyDef = attResp.ActiveDefender.CurrentEnergy; var health = attResp.ActiveDefender.CurrentHealth; var activeDefender = attResp.ActiveDefender.PokemonData.PokemonId; Logger.Debug($"(Gym) - Defender: {activeDefender} Energy={energyDef}, Health={health}"); } count++; // Wait until all attack are done. but not more than 1.5 seconds. var waitTime = (int)(baseAction.ActionStartMs - attResp.BattleLog.ServerMs); if (waitTime < 0) { waitTime = 0; } else if (waitTime > 1200) { waitTime = 1500; } RandomHelper.RandomSleep(waitTime, waitTime + 100); } } Logger.ColoredConsoleWrite(gymColorLog, $"(Gym) - Battle Finished in {count} Rounds."); if (attResp.Result == AttackGymResponse.Types.Result.Success) { if (attResp.BattleLog.State == BattleState.Defeated) { Logger.ColoredConsoleWrite(gymColorLog, "(Gym) - We have lost"); if (numDefenders > 1) { AddVisited(gym.Id, 3600000); } } else if (attResp.BattleLog.State == BattleState.Victory) { Logger.ColoredConsoleWrite(gymColorLog, "(Gym) - We have won"); if (numDefenders > 1) { Logger.Debug("(Gym) - Leaving Battle"); var times = 3; do { attResp = LeaveBattle(gym, client, resp, attResp, lastRetrievedAction); times--; } while (attResp.Result != AttackGymResponse.Types.Result.Success && times > 0); RandomHelper.RandomSleep(800); } else { ReviveAndCurePokemons(client); var pokemons = (client.Inventory.GetPokemons()).ToList(); RandomHelper.RandomSleep(400); gymDetails = client.Fort.GetGymDetails(gym.Id, gym.Latitude, gym.Longitude); Logger.Debug("(Gym) - Gym Details: " + gymDetails); if (gymDetails.GymState.Memberships.Count < 1) { putInGym(client, gym, getPokeToPut(client, buddyPokemonId), pokemons); } } } else if (attResp.BattleLog.State == BattleState.TimedOut) { Logger.ColoredConsoleWrite(gymColorLog, "(Gym) - Timed Out"); } } else { Logger.ColoredConsoleWrite(gymColorLog, "(Gym) - Battle Failed: " + attResp.Result); } return(attResp); } return(null); }
/// <summary> /// Provides a safe way to invoke the <see cref="GymDetailsReceived" /> event. /// </summary> /// <param name="value"></param> public void RaiseGymDetailsReceived(GetGymDetailsResponse value) => GymDetailsReceived?.Invoke(this, value);
private static async Task StartGymAttackLogic(ISession session, FortDetailsResponse fortInfo, GetGymDetailsResponse fortDetails, FortData gym, CancellationToken cancellationToken) { bool fighting = true; var badassPokemon = await session.Inventory.GetHighestCpForGym(6); var pokemonDatas = badassPokemon as PokemonData[] ?? badassPokemon.ToArray(); while (fighting) { // Heal pokemon foreach (var pokemon in pokemonDatas) { if (pokemon.Stamina <= 0) { await RevivePokemon(session, pokemon); } if (pokemon.Stamina < pokemon.StaminaMax) { await HealPokemon(session, pokemon); } } await Task.Delay(4000); int tries = 0; StartGymBattleResponse result; do { tries++; result = await StartBattle(session, pokemonDatas, gym); if (result.Result == StartGymBattleResponse.Types.Result.Unset) { // Try to refresh information about pokemons and gym await session.Inventory.RefreshCachedInventory(); badassPokemon = await session.Inventory.GetHighestCpForGym(6); pokemonDatas = badassPokemon as PokemonData[] ?? badassPokemon.ToArray(); Logger.Write($"Failed to Start Gym Battle at try: {tries}, waiting 20 seconds before make another one.", LogLevel.Gym, ConsoleColor.Red); await Task.Delay(20000); } } while (result.Result == StartGymBattleResponse.Types.Result.Unset && tries <= 10); // If we can't start battle in 10 tries, let's skip the gym if (result.Result == StartGymBattleResponse.Types.Result.Unset) { session.EventDispatcher.Send(new GymErrorUnset { GymName = fortInfo.Name }); break; } if (result.Result != StartGymBattleResponse.Types.Result.Success) { break; } switch (result.BattleLog.State) { case BattleState.Active: Logger.Write($"Time to start Attack Mode", LogLevel.Gym, ConsoleColor.Red); await AttackGym(session, cancellationToken, gym, result); break; case BattleState.Defeated: break; case BattleState.StateUnset: break; case BattleState.TimedOut: break; case BattleState.Victory: fighting = false; break; default: Logger.Write($"Unhandled result starting gym battle:\n{result}"); break; } fortDetails = await session.Client.Fort.GetGymDetails(gym.Id, gym.Latitude, gym.Longitude); if (fortDetails.GymState.FortData.OwnedByTeam == TeamColor.Neutral || fortDetails.GymState.FortData.OwnedByTeam == session.Profile.PlayerData.Team) { break; } } // Finished battling.. OwnedByTeam should be neutral when we reach here if (fortDetails.GymState.FortData.OwnedByTeam == TeamColor.Neutral || fortDetails.GymState.FortData.OwnedByTeam == session.Profile.PlayerData.Team) { await Execute(session, cancellationToken, gym, fortInfo); } else { Logger.Write($"Hmmm, for some reason the gym was not taken over..."); } }
private static async Task DeployPokemonToGym(ISession session, FortDetailsResponse fortInfo, GetGymDetailsResponse fortDetails) { var maxCount = 0; var points = fortDetails.GymState.FortData.GymPoints; if (points < 1600) { maxCount = 1; } else if (points < 4000) { maxCount = 2; } else if (points < 8000) { maxCount = 3; } else if (points < 12000) { maxCount = 4; } else if (points < 16000) { maxCount = 5; } else if (points < 20000) { maxCount = 6; } else if (points < 30000) { maxCount = 7; } else if (points < 40000) { maxCount = 8; } else if (points < 50000) { maxCount = 9; } else { maxCount = 10; } var availableSlots = maxCount - fortDetails.GymState.Memberships.Count(); if (availableSlots > 0) { var pokemon = await GetDeployablePokemon(session); if (pokemon != null) { var response = await session.Client.Fort.FortDeployPokemon(fortInfo.FortId, pokemon.Id); if (response.Result == FortDeployPokemonResponse.Types.Result.Success) { session.EventDispatcher.Send(new GymDeployEvent() { PokemonId = pokemon.PokemonId, Name = fortDetails.Name }); if (session.LogicSettings.GymCollectRewardAfter > 0) { var deployed = await session.Inventory.GetDeployedPokemons(); var count = deployed.Count(); if (count >= session.LogicSettings.GymCollectRewardAfter) { var collectDailyBonusResponse = await session.Client.Player.CollectDailyBonus(); if (collectDailyBonusResponse.Result == CollectDailyBonusResponse.Types.Result.Success) { Logger.Write($"Collected {count * 10} coins", LogLevel.Gym, ConsoleColor.DarkYellow); } } } } } } else { string message = "No action. No FREE slots in GYM " + fortDetails.GymState.Memberships.Count() + "/" + maxCount; Logger.Write(message, LogLevel.Gym, ConsoleColor.White); } }
public void Save(GetGymDetailsResponse fortDetails, FortDetailsResponse fortInfo, string filePath, double currentAltitude) { //write data file try { var data = new Xml.Gym2(); data.Id = fortInfo.FortId; data.Latitude = fortDetails.GymState.FortData.Latitude; data.Longitude = fortDetails.GymState.FortData.Longitude; data.Altitude = currentAltitude; data.Name = fortDetails.Name; data.Description = fortDetails.Description; data.Fp = fortInfo.Fp; data.CooldownCompleteTimestampMs = fortDetails.GymState.FortData.CooldownCompleteTimestampMs; data.GymPoints = fortDetails.GymState.FortData.GymPoints; data.LastModifiedTimestampMs = fortDetails.GymState.FortData.LastModifiedTimestampMs; data.Sponsor = fortDetails.GymState.FortData.Sponsor.ToString(); data.Team = fortDetails.GymState.FortData.OwnedByTeam.ToString(); if (fortDetails.GymState.Memberships != null && fortDetails.GymState.Memberships.Count() > 0) { foreach (var membership in fortDetails.GymState.Memberships) { var m = new Xml.Membership2(); m.Player.Name = membership.TrainerPublicProfile.Name; m.Player.Level = membership.TrainerPublicProfile.Level; m.Pokemon.BattlesAttacked = membership.PokemonData.BattlesAttacked; m.Pokemon.BattlesDefended = membership.PokemonData.BattlesDefended; m.Pokemon.Cp = membership.PokemonData.Cp; m.Pokemon.Hp = membership.PokemonData.StaminaMax; m.Pokemon.HeightM = membership.PokemonData.HeightM; m.Pokemon.WeightKg = membership.PokemonData.WeightKg; m.Pokemon.Id = membership.PokemonData.Id; m.Pokemon.IndividualAttack = membership.PokemonData.IndividualAttack; m.Pokemon.IndividualDefense = membership.PokemonData.IndividualDefense; m.Pokemon.IndividualStamina = membership.PokemonData.IndividualStamina; m.Pokemon.PlayerLevel = membership.TrainerPublicProfile.Level; m.Pokemon.PlayerTeam = fortDetails.GymState.FortData.OwnedByTeam.ToString(); m.Pokemon.IV = membership.PokemonData.GetPerfection(); m.Pokemon.Nickname = membership.PokemonData.Nickname; m.Pokemon.V = CalculatePokemonValue(membership.PokemonData); m.Pokemon.Move1 = membership.PokemonData.Move1.ToString(); m.Pokemon.Move2 = membership.PokemonData.Move2.ToString(); m.Pokemon.Nickname = membership.PokemonData.Nickname; m.Pokemon.Level = membership.PokemonData.NumUpgrades; m.Pokemon.Origin = membership.PokemonData.Origin; m.Pokemon.Type = membership.PokemonData.PokemonId.ToString(); data.Memberships.Add(m); } } foreach (var img in fortInfo.ImageUrls) { data.ImageUrls.Add(img); } Xml.Serializer.SerializeToFile(data, filePath); } catch// (Exception e) { //Logger.Write($"Could not save the gym information file for {fortInfo.FortId} - {e.ToString()}", LogLevel.Error); } }
private static bool ShouldAttackGym(ISession session, GetGymDetailsResponse gymInfos) { // ELLABORATE THE CALCULATION return(false); }
private static bool IsGymFree(ISession session, GetGymDetailsResponse gymInfos) { var membershipCount = gymInfos.GymState.Memberships.ToList().Count; return(session.Profile.PlayerData.Team == gymInfos.GymState.FortData.OwnedByTeam && membershipCount < MaxSlotByPrestige(gymInfos.GymState.FortData.GymPoints)); }
private static async Task <bool> AttackGym(ISession session, CancellationToken cancellationToken, FortData pokeGym, GetGymDetailsResponse gymInfos, int maxTimes) { var distance = LocationUtils.CalculateDistanceInMeters(session.Client.CurrentLatitude, session.Client.CurrentLongitude, pokeGym.Latitude, pokeGym.Longitude); session.EventDispatcher.Send(new FortTargetEvent { Name = gymInfos.Name, Distance = distance }); await session.Navigation.Move(new GeoCoordinate(pokeGym.Latitude, pokeGym.Longitude), session.LogicSettings.WalkingSpeedInKilometerPerHour, null, cancellationToken, session.LogicSettings.DisableHumanWalking); return(IsGymFree(session, gymInfos)); // TODO: KNOW HOW BATTLE WORKS for (int i = 0; i < maxTimes; i++) { var attackResponse = await session.Client.Fort.StartGymBattle(gymInfos.GymState.FortData.Id, gymInfos.GymState.Memberships.First().PokemonData.Id, (await session.Inventory.GetHighestsCp(6)).Select(p => p.Id)); if (attackResponse.Result == StartGymBattleResponse.Types.Result.Success) { session.EventDispatcher.Send(new NoticeEvent() { Message = string.Format("SUCCESSFULLY STARTED GYM BATTLE") }); } else { session.EventDispatcher.Send(new WarnEvent() { Message = string.Format("FAILED TO START GYM BATTLE [{0}]", attackResponse.Result) }); } } }
private static async Task DeployPokemonToGym(ISession session, FortDetailsResponse fortInfo, GetGymDetailsResponse fortDetails, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var points = fortDetails.GymState.FortData.GymPoints; var maxCount = GetGymLevel(points); var availableSlots = maxCount - fortDetails.GymState.Memberships.Count(); if (availableSlots > 0) { var deployed = await session.Inventory.GetDeployedPokemons(); if (!deployed.Any(a => a.DeployedFortId == fortInfo.FortId)) { var pokemon = await GetDeployablePokemon(session); if (pokemon != null) { FortDeployPokemonResponse response = null; try { response = await session.Client.Fort.FortDeployPokemon(fortInfo.FortId, pokemon.Id); } catch (APIBadRequestException) { Logger.Write("Failed to deploy pokemon. Trying again...", LogLevel.Gym, ConsoleColor.Magenta); await Execute(session, cancellationToken, fortDetails.GymState.FortData, fortInfo); return; } if (response?.Result == FortDeployPokemonResponse.Types.Result.Success) { session.EventDispatcher.Send(new GymDeployEvent() { PokemonId = pokemon.PokemonId, Name = fortDetails.Name }); if (session.LogicSettings.GymConfig.CollectCoinAfterDeployed > 0) { var count = deployed.Count() + 1; if (count >= session.LogicSettings.GymConfig.CollectCoinAfterDeployed) { try { if (session.Profile.PlayerData.DailyBonus.NextDefenderBonusCollectTimestampMs <= DateTime.Now.ToUnixTime()) { var collectDailyBonusResponse = await session.Client.Player.CollectDailyDefenderBonus(); if (collectDailyBonusResponse.Result == CollectDailyDefenderBonusResponse.Types.Result.Success) { Logger.Write($"Collected {count * 10} coins", LogLevel.Gym, ConsoleColor.DarkYellow); } else { Logger.Write($"Hmm, we have failed with gaining a reward: {collectDailyBonusResponse}", LogLevel.Gym, ConsoleColor.Magenta); } } else { Logger.Write($"You will be able to collect bonus at {DateTimeFromUnixTimestampMillis(session.Profile.PlayerData.DailyBonus.NextDefenderBonusCollectTimestampMs)}", LogLevel.Info, ConsoleColor.Magenta); } } catch (APIBadRequestException) { Logger.Write("Can't get coins", LogLevel.Warning); //Debug.WriteLine(e.Message, "GYM"); //Debug.WriteLine(e.StackTrace, "GYM"); await Task.Delay(500); } } else { Logger.Write(string.Format("You have only {0} defenders deployed but {1} required to get reward", count, session.LogicSettings.GymConfig.CollectCoinAfterDeployed), LogLevel.Gym, ConsoleColor.Magenta); } } else { Logger.Write("You have disabled reward collecting in config file", LogLevel.Gym, ConsoleColor.Magenta); } } else { Logger.Write(string.Format("Deploy pokemon failed with result: {0}", response.Result), LogLevel.Gym, ConsoleColor.Magenta); } } else { Logger.Write($"You don't have pokemons to be deployed!", LogLevel.Gym); } } else { Logger.Write($"You already have pokemon deployed here", LogLevel.Gym); } } else { string message = string.Format("No action. No FREE slots in GYM {0}/{1} ({2})", fortDetails.GymState.Memberships.Count(), maxCount, points); Logger.Write(message, LogLevel.Gym, ConsoleColor.White); } }
private static async Task StartGymAttackLogic(ISession session, FortDetailsResponse fortInfo, GetGymDetailsResponse fortDetails, FortData gym, CancellationToken cancellationToken) { var defenders = fortDetails.GymState.Memberships.Select(x => x.PokemonData).ToList(); if (session.Profile.PlayerData.Team != fortInfo.TeamColor) { if (session.LogicSettings.GymConfig.MaxGymLevelToAttack < GetGymLevel(gym.GymPoints)) { Logger.Write($"This is gym level {GetGymLevel(gym.GymPoints)} > {session.LogicSettings.GymConfig.MaxGymLevelToAttack} in your config. Bot walk away...", LogLevel.Gym, ConsoleColor.Red); return; } if (session.LogicSettings.GymConfig.MaxDefendersToAttack < defenders.Count) { Logger.Write($"This is gym has {defenders.Count} defender > {session.LogicSettings.GymConfig.MaxDefendersToAttack} in your config. Bot walk away...", LogLevel.Gym, ConsoleColor.Red); return; } } await session.Inventory.RefreshCachedInventory(); var badassPokemon = await session.Inventory.GetHighestCpForGym(6); var pokemonDatas = badassPokemon as PokemonData[] ?? badassPokemon.ToArray(); if (defenders.Count == 0) { return; } Logger.Write("Start battle with : " + string.Join(", ", defenders.Select(x => x.PokemonId.ToString()))); // Heal pokemon foreach (var pokemon in pokemonDatas) { if (pokemon.Stamina <= 0) { await RevivePokemon(session, pokemon); } if (pokemon.Stamina <= 0) { Logger.Write("You are out of revive potions! Can't resurect attacker", LogLevel.Gym, ConsoleColor.Magenta); return; } if (pokemon.Stamina < pokemon.StaminaMax) { await HealPokemon(session, pokemon); } if (pokemon.Stamina < pokemon.StaminaMax) { Logger.Write(string.Format("You are out of healing potions! {0} ({1} CP) haven't got fully healed", pokemon.PokemonId, pokemon.Cp), LogLevel.Gym, ConsoleColor.Magenta); } } await Task.Delay(2000); var index = 0; bool isVictory = true; bool isFailedToStart = false; List <BattleAction> battleActions = new List <BattleAction>(); ulong defenderPokemonId = defenders.First().Id; while (index < defenders.Count()) { cancellationToken.ThrowIfCancellationRequested(); var thisAttackActions = new List <BattleAction>(); StartGymBattleResponse result = null; try { await Task.Delay(2000); result = await StartBattle(session, gym, pokemonDatas, defenders.FirstOrDefault(x => x.Id == defenderPokemonId)); } #pragma warning disable 0168 catch (APIBadRequestException e) #pragma warning restore 0168 { Logger.Write("Can't start battle", LogLevel.Gym); isFailedToStart = true; isVictory = false; _startBattleCounter--; var newFots = await UseNearbyPokestopsTask.UpdateFortsData(session); gym = newFots.FirstOrDefault(w => w.Id == gym.Id); break; } index++; // If we can't start battle in 10 tries, let's skip the gym if (result == null || result.Result == StartGymBattleResponse.Types.Result.Unset) { session.EventDispatcher.Send(new GymErrorUnset { GymName = fortInfo.Name }); isVictory = false; break; } if (result.Result != StartGymBattleResponse.Types.Result.Success) { break; } switch (result.BattleLog.State) { case BattleState.Active: Logger.Write($"Time to start Attack Mode", LogLevel.Gym, ConsoleColor.DarkYellow); thisAttackActions = await AttackGym(session, cancellationToken, gym, result); battleActions.AddRange(thisAttackActions); break; case BattleState.Defeated: isVictory = false; break; case BattleState.StateUnset: isVictory = false; break; case BattleState.TimedOut: isVictory = false; break; case BattleState.Victory: break; default: Logger.Write($"Unhandled result starting gym battle:\n{result}"); break; } var rewarded = battleActions.Select(x => x.BattleResults?.PlayerExperienceAwarded).Where(x => x != null); var lastAction = battleActions.LastOrDefault(); if (lastAction.Type == BattleActionType.ActionTimedOut || lastAction.Type == BattleActionType.ActionUnset || lastAction.Type == BattleActionType.ActionDefeat) { isVictory = false; break; } var faintedPKM = battleActions.Where(x => x != null && x.Type == BattleActionType.ActionFaint).Select(x => x.ActivePokemonId).Distinct(); var livePokemons = pokemonDatas.Where(x => !faintedPKM.Any(y => y == x.Id)); var faintedPokemons = pokemonDatas.Where(x => faintedPKM.Any(y => y == x.Id)); pokemonDatas = livePokemons.Concat(faintedPokemons).ToArray(); if (lastAction.Type == BattleActionType.ActionVictory) { if (lastAction.BattleResults != null) { var exp = lastAction.BattleResults.PlayerExperienceAwarded; var point = lastAction.BattleResults.GymPointsDelta; gym.GymPoints += point; defenderPokemonId = unchecked ((ulong)lastAction.BattleResults.NextDefenderPokemonId); Logger.Write(string.Format("Exp: {0}, Gym points: {1}" /*, Next defender id: {2}"*/, exp, point, defenderPokemonId), LogLevel.Gym, ConsoleColor.Magenta); } continue; } } if (isVictory) { if (gym.GymPoints < 0) { gym.GymPoints = 0; } await Execute(session, cancellationToken, gym, fortInfo); } if (isFailedToStart && _startBattleCounter > 0) { //session.ReInitSessionWithNextBot(); await Execute(session, cancellationToken, gym, fortInfo); } if (_startBattleCounter <= 0) { _startBattleCounter = 3; } }
private static AttackGymResponse AttackGym(FortData gym, Client client, IEnumerable <PokemonData> pokeAttackers, ulong defenderId, int numDefenders, ulong buddyPokemonId) { StopAttack = false; var pokeAttackersIds = pokeAttackers.Select(x => x.Id); var moveSettings = GetMoveSettings(client); GetGymDetailsResponse gymDetails = null; StartGymBattleResponse resp = null; // Sometimes we get a null from startgymBattle so we try to start battle 3 times var numTries = 3; var startOk = false; do { gymDetails = client.Fort.GetGymDetails(gym.Id, gym.Latitude, gym.Longitude); RandomHelper.RandomSleep(200); try { resp = client.Fort.StartGymBattle(gym.Id, defenderId, pokeAttackersIds).Result; if (resp != null && resp.BattleLog != null) { startOk = true; } else { Logger.Info("(Gym) - Start Gym Failed."); Logger.Debug("(Gym) - resp:" + resp); } } catch (Exception ex1) { Logger.Info("(Gym) - Start Gym Failed. Reason:" + ex1); } numTries--; } while (!startOk && numTries > 0 && !StopAttack); if (!startOk) { Logger.Info("(Gym) - Start Gym Failed. After of 3 tries"); return(null); } if (resp.BattleLog.State == BattleState.Active) { Logger.ColoredConsoleWrite(gymColorLog, "(Gym) - Battle Started"); RandomHelper.RandomSleep(2000); var battleActions = new List <BattleAction>(); var lastRetrievedAction = new BattleAction(); var battleStartMs = resp.BattleLog.BattleStartTimestampMs; var attResp = client.Fort.AttackGym(gym.Id, resp.BattleId, battleActions, lastRetrievedAction); var inBattle = (attResp.Result == AttackGymResponse.Types.Result.Success); inBattle = inBattle && (attResp.BattleLog.State == BattleState.Active); var count = 1; var energy = 0; var numVictories = 0; Logger.Debug("attResp: " + attResp); while (inBattle && !StopAttack) { var timeMs = attResp.BattleLog.ServerMs; var move1Settings = moveSettings.FirstOrDefault(x => x.MoveSettings.MovementId == attResp.ActiveAttacker.PokemonData.Move1).MoveSettings; var move2Settings = moveSettings.FirstOrDefault(x => x.MoveSettings.MovementId == attResp.ActiveAttacker.PokemonData.Move2).MoveSettings; battleActions = new List <BattleAction>(); var baseAction = new BattleAction(); baseAction.ActionStartMs = timeMs + RandomNumbers.Next(110, 170); baseAction.TargetIndex = -1; if (attResp.ActiveDefender != null) { baseAction.TargetPokemonId = attResp.ActiveDefender.PokemonData.Id; } if (attResp.ActiveAttacker.PokemonData.Stamina > 0) { baseAction.ActivePokemonId = attResp.ActiveAttacker.PokemonData.Id; } // One each ten times we try to evade attack if (RandomNumbers.Next(1, 10) == 1) { var dodgeAction = new BattleAction(); dodgeAction.ActionStartMs = baseAction.ActionStartMs; dodgeAction.TargetIndex = baseAction.TargetIndex; dodgeAction.TargetPokemonId = baseAction.TargetPokemonId; dodgeAction.ActivePokemonId = baseAction.ActivePokemonId; dodgeAction.Type = BattleActionType.ActionDodge; dodgeAction.DurationMs = 500; battleActions.Add(dodgeAction); Logger.Debug("Dodge Action Added"); baseAction.ActionStartMs = dodgeAction.ActionStartMs + dodgeAction.DurationMs; } if (energy >= Math.Abs(move2Settings.EnergyDelta)) { var specialAttack = new BattleAction(); specialAttack.ActionStartMs = baseAction.ActionStartMs; specialAttack.TargetIndex = baseAction.TargetIndex; specialAttack.TargetPokemonId = baseAction.TargetPokemonId; specialAttack.ActivePokemonId = baseAction.ActivePokemonId; specialAttack.Type = BattleActionType.ActionSpecialAttack; specialAttack.DurationMs = move2Settings.DurationMs; specialAttack.DamageWindowsStartTimestampMs = specialAttack.ActionStartMs + move2Settings.DamageWindowStartMs; specialAttack.DamageWindowsEndTimestampMs = specialAttack.ActionStartMs + move2Settings.DamageWindowEndMs; specialAttack.EnergyDelta = move2Settings.EnergyDelta; battleActions.Add(specialAttack); Logger.Debug("Special Attack Added"); baseAction.ActionStartMs = specialAttack.ActionStartMs + specialAttack.DurationMs; } else { // One each nine times we do not attack if (RandomNumbers.Next(1, 9) != 1) { var normalAttack = new BattleAction(); normalAttack.ActionStartMs = baseAction.ActionStartMs; normalAttack.TargetIndex = baseAction.TargetIndex; normalAttack.TargetPokemonId = baseAction.TargetPokemonId; normalAttack.ActivePokemonId = baseAction.ActivePokemonId; normalAttack.Type = BattleActionType.ActionAttack; normalAttack.DurationMs = baseAction.DurationMs; normalAttack.DamageWindowsStartTimestampMs = normalAttack.ActionStartMs + move1Settings.DamageWindowStartMs; normalAttack.DamageWindowsEndTimestampMs = normalAttack.ActionStartMs + move1Settings.DamageWindowEndMs; normalAttack.EnergyDelta = move1Settings.EnergyDelta; battleActions.Add(normalAttack); Logger.Debug("Normal Attack Added"); baseAction.ActionStartMs = normalAttack.ActionStartMs + normalAttack.DurationMs; } } lastRetrievedAction = attResp.BattleLog.BattleActions.LastOrDefault(x => x.ActivePokemonId != attResp.ActiveAttacker.PokemonData.Id); var str = string.Join(",", battleActions); Logger.Debug("(Gym) - battleActions: " + str); attResp = client.Fort.AttackGym(gym.Id, resp.BattleId, battleActions, lastRetrievedAction); Logger.Debug("attResp: " + attResp); Logger.Debug("attResp BattleActions: "); ShowBattleActions(attResp.BattleLog.BattleActions); inBattle = (attResp.Result == AttackGymResponse.Types.Result.Success); if (inBattle) { inBattle = (attResp.BattleLog.State == BattleState.Active); if (attResp.ActiveAttacker != null) { energy = attResp.ActiveAttacker.CurrentEnergy; var health = attResp.ActiveAttacker.CurrentHealth; var activeAttacker = attResp.ActiveAttacker.PokemonData.PokemonId; Logger.Debug($"(Gym) - Attacker: {activeAttacker} Energy={energy}, Health={health}"); } if (attResp.ActiveDefender != null) { var energyDef = attResp.ActiveDefender.CurrentEnergy; var health = attResp.ActiveDefender.CurrentHealth; var activeDefender = attResp.ActiveDefender.PokemonData.PokemonId; Logger.Debug($"(Gym) - Defender: {activeDefender} Energy={energyDef}, Health={health}"); } count++; // Wait until all attack are done. but not more than 1.5 seconds. var waitTime = (int)(baseAction.ActionStartMs - attResp.BattleLog.ServerMs); if (waitTime < 0) { waitTime = 0; } else if (waitTime > 1200) { waitTime = 1200; } RandomHelper.RandomSleep(waitTime, waitTime + 100); } } Logger.ColoredConsoleWrite(gymColorLog, $"(Gym) - Battle Finished in {count} Rounds."); if (attResp.Result == AttackGymResponse.Types.Result.Success) { switch (attResp.BattleLog.State) { case BattleState.Defeated: Logger.ColoredConsoleWrite(gymColorLog, "(Gym) - We have lost"); if (numDefenders > 1) { AddVisited(gym.Id, 3600000); } break; case BattleState.Victory: Logger.ColoredConsoleWrite(gymColorLog, "(Gym) - We have won"); var nextDefenderID = -1L; foreach (var element in attResp.BattleLog.BattleActions) { if (element.BattleResults != null) { Logger.Info("(Gym) - Gym points: " + element.BattleResults.GymPointsDelta); Logger.Info("(Gym) - Experience Awarded: " + element.BattleResults.PlayerExperienceAwarded); Logger.Debug("(Gym) - Next Pokemon: " + element.BattleResults.NextDefenderPokemonId); if (element.BattleResults.NextDefenderPokemonId != -1) { nextDefenderID = element.BattleResults.NextDefenderPokemonId; } } } if (numDefenders > 1) { Logger.Debug("(Gym) - Leaving Battle"); var times = 3; do { attResp = LeaveBattle(gym, client, resp, attResp, lastRetrievedAction, nextDefenderID); times--; } while (attResp.Result != AttackGymResponse.Types.Result.Success && times > 0); const int secondsBetweenAttacks = 300; Logger.Info($"Waiting {secondsBetweenAttacks} seconds before of a new battle."); for (var i = 0; i < secondsBetweenAttacks + 1; i++) { if (StopAttack) { AddVisited(gym.Id, 3600000); break; } if ((i != 0) && (i % 10 == 0)) { Logger.Info($"Seconds Left {secondsBetweenAttacks-i}"); } if (i % 30 == 0) { Logic.objClient.Map.GetMapObjects().Wait(); } Task.Delay(1000).Wait(); } } else { ReviveAndCurePokemons(client); var pokemons = (client.Inventory.GetPokemons()).ToList(); RandomHelper.RandomSleep(400); gymDetails = client.Fort.GetGymDetails(gym.Id, gym.Latitude, gym.Longitude); Logger.Debug("(Gym) - Gym Details: " + gymDetails); if (gymDetails.GymState.Memberships.Count < 1) { putInGym(client, gym, getPokeToPut(client, buddyPokemonId, gym.GuardPokemonCp), pokemons); } } break; case BattleState.TimedOut: Logger.ColoredConsoleWrite(gymColorLog, "(Gym) - Timed Out"); AddVisited(gym.Id, 1800000); break; } } else { Logger.ColoredConsoleWrite(gymColorLog, "(Gym) - Battle Failed: " + attResp.Result); } return(attResp); } return(null); }
private static async Task DeployPokemonToGym(ISession session, FortDetailsResponse fortInfo, GetGymDetailsResponse fortDetails) { var pokemon = await GetDeployablePokemon(session); if (pokemon != null) { var response = await session.Client.Fort.FortDeployPokemon(fortInfo.FortId, pokemon.Id); if (response.Result == FortDeployPokemonResponse.Types.Result.Success) { session.EventDispatcher.Send(new GymDeployEvent() { PokemonId = pokemon.PokemonId, Name = fortDetails.Name }); } } }
private ObservableCollection <GymMembershipWrapper> GetCurrentMembers(GetGymDetailsResponse currentGymInfo) => new ObservableCollection <GymMembershipWrapper>( currentGymInfo.GymState.Memberships.Select(m => new GymMembershipWrapper(m)));
private static async Task DeployPokemonToGym(ISession session, FortDetailsResponse fortInfo, GetGymDetailsResponse fortDetails) { var maxCount = 0; var points = fortDetails.GymState.FortData.GymPoints; if (points < 1600) { maxCount = 1; } else if (points < 4000) { maxCount = 2; } else if (points < 8000) { maxCount = 3; } else if (points < 12000) { maxCount = 4; } else if (points < 16000) { maxCount = 5; } else if (points < 20000) { maxCount = 6; } else if (points < 30000) { maxCount = 7; } else if (points < 40000) { maxCount = 8; } else if (points < 50000) { maxCount = 9; } else { maxCount = 10; } var availableSlots = maxCount - fortDetails.GymState.Memberships.Count(); if (availableSlots > 0) { var pokemon = await GetDeployablePokemon(session); if (pokemon != null) { var response = await session.Client.Fort.FortDeployPokemon(fortInfo.FortId, pokemon.Id); if (response.Result == FortDeployPokemonResponse.Types.Result.Success) { session.EventDispatcher.Send(new GymDeployEvent() { PokemonId = pokemon.PokemonId, Name = fortDetails.Name }); } } } else { string message = "No action. No FREE slots in GYM " + fortDetails.GymState.Memberships.Count() + "/" + maxCount; Logger.Write(message, LogLevel.Gym, ConsoleColor.White); } }