private static AttackGymResponse LeaveBattle(FortData gym, Client client, StartGymBattleResponse resp, AttackGymResponse attResp, BattleAction lastRetrievedAction, long nextDefenderID) { AttackGymResponse ret = attResp; var times = 3; var exit = false; do { var timeMs = ret.BattleLog.ServerMs; var attack = new BattleAction(); attack.Type = BattleActionType.ActionPlayerQuit; attack.TargetPokemonId = (ulong)nextDefenderID; if (attResp.ActiveAttacker != null) { attack.ActivePokemonId = attResp.ActiveAttacker.PokemonData.Id; } var battleActions = new List <BattleAction>(); battleActions.Add(attack); lastRetrievedAction = new BattleAction(); ret = client.Fort.AttackGym(gym.Id, resp.BattleId, battleActions, lastRetrievedAction); Logger.Debug($"ret {times}: {ret}"); Logger.Debug("ret BattleActions: "); ShowBattleActions(attResp.BattleLog.BattleActions); times--; if (ret.Result == AttackGymResponse.Types.Result.Success) { foreach (var element in ret.BattleLog.BattleActions) { if (element.Type == BattleActionType.ActionPlayerQuit) { Logger.Info("(Gym) - Gym points: " + element.BattleResults.GymPointsDelta); Logger.Info("(Gym) - Experience Awarded: " + element.BattleResults.PlayerExperienceAwarded); Logger.Debug("(Gym) - Next Pokemon: " + element.BattleResults.NextDefenderPokemonId); exit = true; } } } } while (!exit && times > 0); return(ret); }
private static AttackGymResponse LeaveBattle(FortData gym, Client client, StartGymBattleResponse resp, AttackGymResponse attResp, BattleAction lastRetrievedAction) { var timeMs = attResp.BattleLog.ServerMs; var attack = new BattleAction(); attack.Type = BattleActionType.ActionPlayerQuit; attack.TargetIndex = -1; if (attResp.ActiveAttacker != null) { attack.ActivePokemonId = attResp.ActiveAttacker.PokemonData.Id; } var battleActions = new List <BattleAction>(); battleActions.Add(attack); lastRetrievedAction = new BattleAction(); AttackGymResponse ret; var times = 3; do { ret = client.Fort.AttackGym(gym.Id, resp.BattleId, battleActions, lastRetrievedAction); times--; } while (ret.Result != AttackGymResponse.Types.Result.Success && times > 0); return(ret); }
/// <summary> /// Provides a safe way to invoke the <see cref="AttackGymReceived" /> event. /// </summary> /// <param name="value"></param> public void RaiseAttackGymReceived(AttackGymResponse value) => AttackGymReceived?.Invoke(this, value);
// ReSharper disable once UnusedParameter.Local private static async Task <List <BattleAction> > AttackGym(ISession session, CancellationToken cancellationToken, FortData currentFortData, StartGymBattleResponse startResponse) { long serverMs = startResponse.BattleLog.BattleStartTimestampMs; var lastActions = startResponse.BattleLog.BattleActions.ToList(); Logger.Write($"Gym battle started; fighting trainer: {startResponse.Defender.TrainerPublicProfile.Name}", LogLevel.Gym, ConsoleColor.Green); Logger.Write($"We are attacking: {startResponse.Defender.ActivePokemon.PokemonData.PokemonId}", LogLevel.Gym, ConsoleColor.White); Console.WriteLine(Environment.NewLine); int loops = 0; List <BattleAction> emptyActions = new List <BattleAction>(); BattleAction emptyAction = new BattleAction(); PokemonData attacker = null; PokemonData defender = null; _currentAttackerEnergy = 0; long lastApiCallTime = DateTime.Now.ToUnixTime(); while (true) { try { cancellationToken.ThrowIfCancellationRequested(); TimedLog("Starts loop"); var last = lastActions.LastOrDefault(); if (last?.Type == BattleActionType.ActionPlayerJoin) { await Task.Delay(3000); TimedLog("Sleep after join battle"); } TimedLog("Getting actions"); var attackActionz = last == null || last.Type == BattleActionType.ActionVictory || last.Type == BattleActionType.ActionDefeat ? emptyActions : await GetActions(session, serverMs, attacker, defender, _currentAttackerEnergy); TimedLog(string.Format(" Going to make attack : {0}", string.Join(", ", attackActionz.Select(s => string.Format("{0} -> {1}", s.Type, s.DurationMs))))); BattleAction a2 = (last == null || last.Type == BattleActionType.ActionVictory || last.Type == BattleActionType.ActionDefeat ? emptyAction : last); AttackGymResponse attackResult = null; try { long timeBefore = DateTime.Now.ToUnixTime(); var attackTime = attackActionz.Sum(x => x.DurationMs); int attackTimeCorrected = attackTime - (int)(timeBefore - lastApiCallTime); TimedLog(string.Format("Waiting for attack to be prepared: {0} (last call was {1}, after correction {2})", attackTime, lastApiCallTime, attackTimeCorrected > 0 ? attackTimeCorrected : 0)); if (attackTimeCorrected > 0) { await Task.Delay(attackTimeCorrected); } if (attackActionz.Any(a => a.Type == BattleActionType.ActionSpecialAttack)) { var damageWindow = attackActionz.Sum(s => s.DamageWindowsEndTimestampMs - s.DamageWindowsStartTimestampMs); TimedLog(string.Format("Waiting extra {0}ms for damage window.", damageWindow)); await Task.Delay((int)damageWindow); } TimedLog("Start making attack"); attackResult = await session.Client.Fort.AttackGym(currentFortData.Id, startResponse.BattleId, attackActionz, a2); TimedLog(string.Format("Finished making attack: {0}, Battle finished at: {1}", attackResult.BattleLog.BattleStartTimestampMs, attackResult.BattleLog.BattleEndTimestampMs)); lastApiCallTime = DateTime.Now.ToUnixTime(); } catch (APIBadRequestException) { Logger.Write("Bad attack gym", LogLevel.Warning); TimedLog(string.Format("Last retrieved action was: {0}", a2)); TimedLog(string.Format("Actions to perform were: {0}", string.Join(", ", attackActionz))); TimedLog(string.Format("Attacker was: {0}, defender was: {1}", attacker, defender)); continue; }; loops++; if (attackResult.Result == AttackGymResponse.Types.Result.Success) { TimedLog("Attack success"); defender = attackResult.ActiveDefender?.PokemonData; if (attackResult.BattleLog != null && attackResult.BattleLog.BattleActions.Count > 0) { lastActions.AddRange(attackResult.BattleLog.BattleActions); } serverMs = attackResult.BattleLog.ServerMs; switch (attackResult.BattleLog.State) { case BattleState.Active: TimedLog("Battlestate active start"); _currentAttackerEnergy = attackResult.ActiveAttacker.CurrentEnergy; if (attacker == null) { attacker = attackResult.ActiveAttacker.PokemonData; } if (attacker.Id != attackResult?.ActiveAttacker?.PokemonData.Id) { attacker = attackResult.ActiveAttacker.PokemonData; await Task.Delay(2000); Logger.Write(string.Format("We ware fainted in battle, new attacker is: {0} ({1} CP){2}", attacker.PokemonId, attacker.Cp, Environment.NewLine), LogLevel.Info, ConsoleColor.Magenta); } Console.SetCursorPosition(0, Console.CursorTop - 1); Logger.Write($"(GYM ATTACK) : Defender {attackResult.ActiveDefender.PokemonData.PokemonId.ToString() } HP {attackResult.ActiveDefender.CurrentHealth} - Attacker {attackResult.ActiveAttacker.PokemonData.PokemonId.ToString()} HP/Sta {attackResult.ActiveAttacker.CurrentHealth}/{attackResult.ActiveAttacker.CurrentEnergy} "); break; case BattleState.Defeated: Logger.Write( $"We were defeated... (AttackGym)"); return(lastActions); case BattleState.TimedOut: Logger.Write( $"Our attack timed out...:"); return(lastActions); case BattleState.StateUnset: Logger.Write( $"State was unset?: {attackResult}"); return(lastActions); case BattleState.Victory: Logger.Write( $"We were victorious!: "); return(lastActions); default: Logger.Write( $"Unhandled attack response: {attackResult}"); continue; } Debug.WriteLine($"{attackResult}", "GYM: " + DateTime.Now.ToUnixTime()); } else { Logger.Write($"Unexpected attack result:\n{attackResult}"); break; } TimedLog("Finished attack"); } catch (APIBadRequestException e) { Logger.Write("Bad request send to server -", LogLevel.Warning); TimedLog("NOT finished attack"); TimedLog(e.Message); }; } return(lastActions); }