public static IEnumerable <int> DeployBalloons() { yield return(dragonAttack ? 2000 : (babyLoon ? 500 : 0)); if (balloon?.Count > 0) { if (!dragonAttack || balloon.Count > 10) { foreach (var t in Deploy.AlongLine(balloon, AllInOnePushDeploy.AttackLine.Item1, AllInOnePushDeploy.AttackLine.Item2, balloon.Count, 2)) { yield return(t); } } else { var count = balloon.Count / 2; foreach (var t in Deploy.AtPoint(balloon, AllInOnePushDeploy.FirstFunnellingPoint, count)) { yield return(t); } foreach (var t in Deploy.AtPoint(balloon, AllInOnePushDeploy.SecondFunnellingPoint, count)) { yield return(t); } } } }
public static IEnumerable <int> DeployGiants() { var jumpSpellCount = jumpSpell?.Sum(u => u.Count); if ((useJump && jumpSpellCount >= 2) || (!useJump && jumpSpellCount >= 1)) { foreach (var unit in jumpSpell) { foreach (var t in Deploy.AtPoint(unit, AllInOnePushDeploy.FirstJumpPoint)) { yield return(t); } } } if (giant?.Count > 0) { Log.Info($"[{AllInOnePushDeploy.AttackName}] deploy Giants ..."); foreach (var t in Deploy.AlongLine(giant, AllInOnePushDeploy.FirstFunnellingPoint, AllInOnePushDeploy.SecondFunnellingPoint, 8, 4)) { yield return(t); } var waves = wizard?.Count >= 8 ? 2 : 1; foreach (var f in DeployWizard(waves)) { yield return(f); } foreach (var f in DeployWB()) { yield return(f); } foreach (var t in Deploy.AtPoint(giant, AllInOnePushDeploy.Origin, giant.Count)) { yield return(t); } } if (clanCastle?.Count > 0 && AllInOnePushDeploy.ClanCastleSettings == 2) { foreach (var t in Deploy.AtPoint(clanCastle, AllInOnePushDeploy.Origin)) { yield return(t); } } //if one golem deploy after funnlling if (golem?.Count > 0) { Log.Info($"[{AllInOnePushDeploy.AttackName}] deploy Golem ..."); foreach (var t in Deploy.AlongLine(golem, AllInOnePushDeploy.AttackLine.Item1, AllInOnePushDeploy.AttackLine.Item2, golem.Count, golem.Count)) { yield return(t); } } }
public static IEnumerable <int> DeployMinions() { if (minion?.Count > 0) { foreach (var t in Deploy.AlongLine(minion, AllInOnePushDeploy.AttackLine.Item1, AllInOnePushDeploy.AttackLine.Item2, minion.Count, 4)) { yield return(t); } } }
public static IEnumerable <int> DeployBabyDragons() { if (babyDragon?.Count > 0) { foreach (var t in Deploy.AlongLine(babyDragon, AllInOnePushDeploy.FirstFunnellingPoint, AllInOnePushDeploy.SecondFunnellingPoint, babyDragon.Count, 4, 50)) { yield return(t); } } }
public static IEnumerable <int> DeployWizard(int waves = 1) { if (wizard?.Count > 0) { var count = wizard.Count / waves; foreach (var t in Deploy.AlongLine(wizard, AllInOnePushDeploy.FirstFunnellingPoint, AllInOnePushDeploy.SecondFunnellingPoint, count, 4)) { yield return(t); } } }
public static IEnumerable <int> DeployUnusedTroops() { // Check unit bar for unused troops Log.Warning($"{AllInOnePushDeploy.AttackName} search for unused troops !!"); var unusedTroops = Deploy.GetTroops(); var spell = unusedTroops.Extract(DeployElementType.Spell); if (unusedTroops.Sum(u => u.Count) > 0) { unusedTroops.OrderForDeploy(); foreach (var u in unusedTroops) { if (u?.Count > 0) { Log.Warning($"we found {u.Count}x {u.PrettyName}"); } } Log.Info($"[{AllInOnePushDeploy.AttackName}] deploy unused troops"); foreach (var unit in unusedTroops) { if (unit?.Count > 0) { if (unit.IsRanged) { foreach (var t in Deploy.AlongLine(unit, AllInOnePushDeploy.FirstFunnellingPoint, AllInOnePushDeploy.SecondFunnellingPoint, unit.Count, 4)) { yield return(t); } } else { foreach (var t in Deploy.AtPoint(unit, AllInOnePushDeploy.Origin, unit.Count)) { yield return(t); } } } } } else { Log.Info($"[{AllInOnePushDeploy.AttackName}] all Troops have been deployed"); } }
public static IEnumerable <int> AirAttack(int customOrder) { Log.Info($"[{AllInOnePushDeploy.AttackName}] 'Air Attack' has been activated"); DeploymentMethods.wallbreaker = AllInOnePushDeploy.deployElements.ExtractOne(DeployId.WallBreaker); DeploymentMethods.balloon = AllInOnePushDeploy.deployElements.ExtractOne(DeployId.Balloon); DeploymentMethods.minion = AllInOnePushDeploy.deployElements.ExtractOne(DeployId.Minion); DeploymentMethods.babyDragon = AllInOnePushDeploy.deployElements.ExtractOne(DeployId.BabyDragon); DeploymentMethods.dragon = AllInOnePushDeploy.deployElements.ExtractOne(DeployId.Dragon); DeploymentMethods.lava = AllInOnePushDeploy.deployElements.ExtractOne(DeployId.LavaHound); DeploymentMethods.spells = AllInOnePushDeploy.deployElements.Extract(DeployElementType.Spell); DeploymentMethods.lightingSpell = DeploymentMethods.spells.ExtractOne(DeployId.Lightning); DeploymentMethods.eq = DeploymentMethods.spells.Extract(u => u.Id == DeployId.Earthquake); DeploymentMethods.hasteSpell = DeploymentMethods.spells.Extract(u => u.Id == DeployId.Haste); DeploymentMethods.rageSpell = DeploymentMethods.spells.Extract(u => u.Id == DeployId.Rage); DeploymentMethods.freezeSpell = DeploymentMethods.spells.ExtractOne(DeployId.Freeze); DeploymentMethods.clanCastle = AllInOnePushDeploy.deployElements.ExtractOne(DeployId.ClanCastle); DeploymentMethods.heroes = AllInOnePushDeploy.deployElements.Extract(x => x.IsHero); DeploymentMethods.warden = DeploymentMethods.heroes.ExtractOne(u => u.ElementType == DeployElementType.HeroWarden); DeploymentMethods.queen = DeploymentMethods.heroes.ExtractOne(DeployId.Queen); DeploymentMethods.dragonAttack = DeploymentMethods.dragon?.Count >= 5 ? true : false; DeploymentMethods.babyLoon = DeploymentMethods.babyDragon?.Count >= 7 ? true : false; DeploymentMethods.lavaloonion = DeploymentMethods.balloon?.Count >= 15 ? true : false; if (DeploymentMethods.lightingSpell?.Count >= 2) { foreach (var t in DeploymentMethods.ZapAirDefense()) { yield return(t); } } if (DeploymentMethods.lightingSpell?.Count >= 2) { foreach (var t in DeploymentMethods.ZapAirDefense()) { yield return(t); } } if (customOrder == 1) { foreach (var t in DeploymentMethods.DeployInCustomOrderAir(AllInOnePushDeploy.CustomOrderList)) { yield return(t); } } else { if (DeploymentMethods.babyLoon) { foreach (var t in DeploymentMethods.AirFunnelling()) { yield return(t); } foreach (var t in DeploymentMethods.DeployBabyDragons()) { yield return(t); } foreach (var t in DeploymentMethods.DeployBalloons()) { yield return(t); } foreach (var t in DeploymentMethods.DeployLava()) { yield return(t); } } else if (DeploymentMethods.dragonAttack) { foreach (var t in DeploymentMethods.AirFunnelling()) { yield return(t); } foreach (var t in DeploymentMethods.DeployLava()) { yield return(t); } foreach (var t in DeploymentMethods.DeployDragons()) { yield return(t); } foreach (var t in DeploymentMethods.DeployBalloons()) { yield return(t); } } else if (DeploymentMethods.lavaloonion) { foreach (var t in DeploymentMethods.DeployBalloons()) { yield return(t); } foreach (var t in DeploymentMethods.DeployLava()) { yield return(t); } if (DeploymentMethods.clanCastle?.Count > 0) { foreach (var t in Deploy.AtPoint(DeploymentMethods.clanCastle, AllInOnePushDeploy.Origin)) { yield return(t); } } foreach (var t in DeploymentMethods.DeployDragons()) { yield return(t); } foreach (var t in DeploymentMethods.DeployBabyDragons()) { yield return(t); } } } if (DeploymentMethods.clanCastle?.Count > 0) { foreach (var t in Deploy.AtPoint(DeploymentMethods.clanCastle, AllInOnePushDeploy.Origin)) { yield return(t); } } if (DeploymentMethods.warden?.Count > 0) { foreach (var t in Deploy.AtPoint(DeploymentMethods.warden, AllInOnePushDeploy.Origin)) { yield return(t); } DeploymentMethods.isWarden = true; } else { DeploymentMethods.isWarden = false; } // Start with haste <IF> it's more than or equal rages count <ELSE> start with rages. var firstSpell = DeploymentMethods.hasteSpell?.Sum(u => u.Count) >= DeploymentMethods.rageSpell?.Sum(u => u.Count) ? DeploymentMethods.hasteSpell : DeploymentMethods.rageSpell; var secondSpell = firstSpell == DeploymentMethods.hasteSpell ? DeploymentMethods.rageSpell : DeploymentMethods.hasteSpell; var firstSpellUnit = firstSpell.FirstOrDefault()?.Count > 0 ? firstSpell.FirstOrDefault() : firstSpell.LastOrDefault(); var secondSpellUnit = secondSpell.FirstOrDefault()?.Count > 0 ? secondSpell.FirstOrDefault() : secondSpell.LastOrDefault(); var line = AllInOnePushDeploy.FirstHasteLine; // Todo: deploy rages for TH8, 2 on the first line then 1 on the second line. if (firstSpellUnit?.Count > 0) { var count = firstSpellUnit.Count >= 3 ? 3 : firstSpellUnit.Count; foreach (var t in Deploy.AlongLine(firstSpellUnit, line.Item1, line.Item2, count, count, 250)) { yield return(t); } line = AllInOnePushDeploy.FirstRageLine; } foreach (var t in DeploymentMethods.DeployMinions()) { yield return(t); } yield return(4500); if (secondSpellUnit?.Count > 0) { var count = secondSpellUnit.Count >= 3 ? 3 : secondSpellUnit.Count; foreach (var t in Deploy.AlongLine(secondSpellUnit, line.Item1, line.Item2, count, count, 250)) { yield return(t); } line = AllInOnePushDeploy.SecondHasteLine; } else { if (firstSpell?.Sum(u => u.Count) > 0) { firstSpellUnit = firstSpell.FirstOrDefault().Count > 0 ? firstSpell.FirstOrDefault() : firstSpell.LastOrDefault(); var count = firstSpellUnit.Count >= 3 ? 3 : firstSpellUnit.Count; foreach (var t in Deploy.AlongLine(firstSpellUnit, line.Item1, line.Item2, count, count, 250)) { yield return(t); } line = AllInOnePushDeploy.SecondHasteLine; } } // Use freeze if inferno is found if (DeploymentMethods.freezeSpell?.Count > 0) { var infernos = InfernoTower.Find(); // Find and watch inferno towers if (infernos != null) { foreach (var inferno in infernos) { inferno.FirstActivated += DropFreeze; inferno.StartWatching(); } } } if (DeploymentMethods.isWarden) { DeploymentMethods.warden.Select(); DeploymentMethods.warden.Select(); } yield return(4000); if (firstSpell?.Sum(u => u.Count) > 0) { foreach (var unit in firstSpell) { var count = unit.Count >= 3 ? 3 : unit.Count; foreach (var t in Deploy.AlongLine(unit, line.Item1, line.Item2, count, count, 250)) { yield return(t); } } line = AllInOnePushDeploy.SecondRageLine; } if (secondSpell?.Sum(u => u.Count) > 0) { secondSpellUnit = secondSpell.FirstOrDefault().Count > 0 ? secondSpell.FirstOrDefault() : secondSpell.LastOrDefault(); foreach (var unit in secondSpell) { var count = unit.Count >= 3 ? 3 : unit.Count; foreach (var t in Deploy.AlongLine(unit, line.Item1, line.Item2, count, count, 250)) { yield return(t); } } } foreach (var t in DeploymentMethods.DeployWB()) { yield return(t); } yield return(4000); if (DeploymentMethods.heroes.Any()) { foreach (var hero in DeploymentMethods.heroes.Where(u => u.Count > 0)) { foreach (var t in Deploy.AtPoint(hero, AllInOnePushDeploy.Origin)) { yield return(t); } } Deploy.WatchHeroes(DeploymentMethods.heroes); } if (DeploymentMethods.queen?.Count > 0) { foreach (var t in Deploy.AtPoint(DeploymentMethods.queen, AllInOnePushDeploy.Origin)) { yield return(t); } Deploy.WatchHeroes(new List <DeployElement> { DeploymentMethods.queen }); } foreach (var w in DeploymentMethods.DeployUnusedTroops()) { yield return(w); } }
public override IEnumerable <int> AttackRoutine() { // Set start battle time. startTime = DateTime.Now; int waveLimit = UserSettings.WaveSize; int waveDelay = (int)(UserSettings.WaveDelay * 1000); int heroesIndex = -1; // Set the core point of the base SmartFourFingersHelper.SetCore(); if (!IsTargetsCalculated) { SmartFourFingersHelper.CalculateTargets(); } // Points to draw lines in deploy extends area. var topLeft = new PointFT((float)GameGrid.MaxX - 2, (float)GameGrid.DeployExtents.MaxY); var topRight = new PointFT((float)GameGrid.DeployExtents.MaxX, (float)GameGrid.MaxY - 2); var rightTop = new PointFT((float)GameGrid.DeployExtents.MaxX, (float)GameGrid.MinY + 2); var rightBottom = new PointFT((float)GameGrid.MaxX - 2, (float)GameGrid.DeployExtents.MinY); // Move 8 tiles from bottom corner due to unitsbar. var bottomLeft = new PointFT((float)GameGrid.DeployExtents.MinX, (float)GameGrid.MinY + 8); var bottomRight = new PointFT((float)GameGrid.MinX + 8, (float)GameGrid.DeployExtents.MinY); var leftTop = new PointFT((float)GameGrid.MinX + 2, (float)GameGrid.DeployExtents.MaxY); var leftBottom = new PointFT((float)GameGrid.DeployExtents.MinX, (float)GameGrid.MaxY - 2); var linesPointsList = new List <PointFT> { topLeft, topRight, rightTop, rightBottom, bottomLeft, bottomRight, leftBottom, leftTop }; // Main four lines of attack. var topRightLine = new Tuple <PointFT, PointFT>(topRight, rightTop); var bottomRightLine = new Tuple <PointFT, PointFT>(bottomRight, rightBottom); var bottomLeftLine = new Tuple <PointFT, PointFT>(bottomLeft, leftBottom); var topLeftLine = new Tuple <PointFT, PointFT>(topLeft, leftTop); // List of the four attack lines in clocwise order AttackLines = new List <Tuple <PointFT, PointFT> > { topRightLine, bottomRightLine, bottomLeftLine, topLeftLine }; var deployHeroesAt = GetCurrentSetting("Deploy Heroes At"); var target = SmartFourFingersHelper.GetHeroesTarget(deployHeroesAt); // Search for target if not found for 3 more times if (target.X == 0f && target.Y == 0f) { for (var i = 1; i <= 3; i++) { yield return(1000); target = SmartFourFingersHelper.GetHeroesTarget(deployHeroesAt); if (target.X != 0f || target.Y != 0f) { break; } } } var nearestRedPointToTarget = GameGrid.RedPoints.OrderBy(p => p.DistanceSq(target)).FirstOrDefault(); var nearestLinePoint = linesPointsList.OrderBy(p => p.DistanceSq(nearestRedPointToTarget)).FirstOrDefault(); heroesIndex = AttackLines.FindIndex(u => (u.Item1.X == nearestLinePoint.X && u.Item1.Y == nearestLinePoint.Y) || (u.Item2.X == nearestLinePoint.X && u.Item2.Y == nearestLinePoint.Y)); var units = Deploy.GetTroops(); var heroes = units.Extract(x => x.IsHero); var cc = units.ExtractOne(u => u.ElementType == DeployElementType.ClanTroops); var spells = units.Extract(u => u.ElementType == DeployElementType.Spell); units.OrderForDeploy(); // Set first attack line // Start from the next line to user defined to end with user defined line var line = AttackLines.NextOf(AttackLines[heroesIndex]); var index = AttackLines.FindIndex(u => u.Item1.X == line.Item1.X && u.Item1.Y == line.Item1.Y); var deploymentMode = GetCurrentSetting("Set Troops Deployment"); if (deploymentMode == 2) { AddFakeTargets(); } var targetsCount = TargetsAtLine[index]; Log.Info($"{AttackName} {Version} starts"); var deployCC = GetCurrentSetting("CC Deployment"); if (deployCC == 0 && cc?.Count > 0) { Log.Info($"{AttackName} Deploy Clan Castle troops first"); foreach (var t in Deploy.AlongLine(cc, line.Item1, line.Item2, 1, 1, 0, waveDelay)) { yield return(t); } } // Start troops deployment on four sides. for (var i = 4; i >= 1; i--) { Log.Info($"Targets at this side = {targetsCount} targets from total {TotalTargetsCount} targets"); foreach (var unit in units) { if (unit?.Count > 0) { var count = deploymentMode == 0 ? unit.Count / i : (TotalTargetsCount > 0 ? unit.Count * targetsCount / TotalTargetsCount : 0); var housing = unit.UnitData.HousingSpace; var fingers = housing < 4 ? (count < 8 ? count : 4) : 1; Log.Info($"{AttackName} Deploy {count}x {unit.PrettyName}"); foreach (var t in Deploy.AlongLine(unit, line.Item1, line.Item2, count, fingers, 0, waveDelay)) { yield return(t); } } } if (i != 1) { line = AttackLines.NextOf(AttackLines[index]); index = AttackLines.FindIndex(u => u.Item1.X == line.Item1.X && u.Item1.Y == line.Item1.Y); TotalTargetsCount -= targetsCount; targetsCount = TargetsAtLine[index]; } } if (deployCC == 1 && cc?.Count > 0) { Log.Info($"{AttackName} Deploy Clan Castle troops"); foreach (var t in Deploy.AlongLine(cc, line.Item1, line.Item2, 1, 1, 0, waveDelay)) { yield return(t); } } if (heroes.Any()) { Log.Info($"{AttackName} Deploy Heroes"); foreach (var hero in heroes.Where(u => u.Count > 0)) { foreach (var t in Deploy.AlongLine(hero, line.Item1, line.Item2, 1, 1, 0, waveDelay)) { yield return(t); } } Deploy.WatchHeroes(heroes, 5000); } // Call FinalizeAttack and ForceZap at the same time var zapSpells = Deploy.GetTroops().Extract(u => u.ElementType == DeployElementType.Spell); if (spells.Extract(u => u.Id == DeployId.Lightning).Sum(u => u.Count) > 0 || spells.Extract(u => u.Id == DeployId.Earthquake).Sum(u => u.Count) > 0) { var finalize = this.FinalizeAttack(units).GetEnumerator(); var force = ForceZap().GetEnumerator(); var firstEnumMoreItems = finalize.MoveNext(); var secondEnumMoreItems = force.MoveNext(); // Start both FinalizeAttack and ForceZap while (firstEnumMoreItems && secondEnumMoreItems) { firstEnumMoreItems = finalize.MoveNext(); secondEnumMoreItems = force.MoveNext(); yield return(200); } // Complete ForceZap if FinalizeAttack finished while (!firstEnumMoreItems && secondEnumMoreItems) { secondEnumMoreItems = force.MoveNext(); yield return(200); } // Complete FinalizeAttack if ForceZap finished while (!secondEnumMoreItems && firstEnumMoreItems) { firstEnumMoreItems = finalize.MoveNext(); yield return(200); } } else { yield break; } }
public static IEnumerable <int> DeployGolems() { if (golem?.Count >= 2) { Log.Info($"[{AllInOnePushDeploy.AttackName}] deploy Golems troops .. "); foreach (var t in Deploy.AlongLine(golem, AllInOnePushDeploy.AttackLine.Item1, AllInOnePushDeploy.AttackLine.Item2, golem.Count, golem.Count)) { yield return(t); } if (AllInOnePushDeploy.ClanCastleSettings == 1) { if (clanCastle?.Count > 0) { foreach (var t in Deploy.AtPoint(clanCastle, AllInOnePushDeploy.Origin)) { yield return(t); } } } yield return(new Random().Next(800, 1500)); var waves = wizard?.Count >= 12 ? 2 : 1; foreach (var f in DeployWizard(waves)) { yield return(f); } } else if (golem?.Count == 1 && AllInOnePushDeploy.ClanCastleSettings == 1) { if (clanCastle?.Count > 0) { foreach (var t in Deploy.AtPoint(golem, AllInOnePushDeploy.FirstFunnellingPoint, golem.Count)) { yield return(t); } foreach (var t in Deploy.AtPoint(clanCastle, AllInOnePushDeploy.SecondFunnellingPoint)) { yield return(t); } yield return(1000); } } else { if (golem?.Count > 0 && healer?.Count == null) { foreach (var t in Deploy.AtPoint(golem, AllInOnePushDeploy.Origin)) { yield return(t); } } if (AllInOnePushDeploy.ClanCastleSettings == 1) { if (clanCastle?.Count > 0) { foreach (var t in Deploy.AtPoint(clanCastle, AllInOnePushDeploy.Origin)) { yield return(t); } } } } }
public static IEnumerable <int> DeployNormalTroops() { Log.Info($"[{AllInOnePushDeploy.AttackName}] deploy rest of troops"); if (witch?.Count > 4) { if (bowler?.Count > 0) { foreach (var t in Deploy.AlongLine(bowler, AllInOnePushDeploy.FirstFunnellingPoint, AllInOnePushDeploy.SecondFunnellingPoint, bowlerFunnelCount, 4)) { yield return(t); } } } if (bowler?.Count > 0) { foreach (var t in Deploy.AtPoint(bowler, AllInOnePushDeploy.Origin, bowler.Count)) { yield return(t); } } if (witch?.Count > 0) { foreach (var t in Deploy.AtPoint(witch, AllInOnePushDeploy.Origin, witch.Count)) { yield return(t); } } if (clanCastle?.Count > 0) { Log.Info($"[{AllInOnePushDeploy.AttackName}] Deploying {clanCastle.PrettyName}"); foreach (var t in Deploy.AtPoint(clanCastle, AllInOnePushDeploy.Origin)) { yield return(t); } } if (healer?.Count > 0) { foreach (var t in Deploy.AtPoint(healer, AllInOnePushDeploy.Origin, healer.Count)) { yield return(t); } } AllInOnePushDeploy.deployElements.OrderForDeploy(); foreach (var unit in AllInOnePushDeploy.deployElements) { Log.Info($"[{AllInOnePushDeploy.AttackName}] deploy any remaining troops"); if (unit?.Count > 0) { if (unit.IsRanged) { foreach (var t in Deploy.AlongLine(unit, AllInOnePushDeploy.FirstFunnellingPoint, AllInOnePushDeploy.SecondFunnellingPoint, unit.Count, 4)) { yield return(t); } } else { foreach (var t in Deploy.AtPoint(unit, AllInOnePushDeploy.Origin, unit.Count)) { yield return(t); } } } } foreach (var w in DeployWizard()) { yield return(w); } foreach (var w in DeployUnusedTroops()) { yield return(w); } }
public override IEnumerable <int> AttackRoutine() { var DE = DarkElixirStorage.Find()?.FirstOrDefault()?.Location.GetCenter(); //set the target if (DE == null) { for (var i = 1; i <= 3; i++) { Log.Warning($"bot didn't found the DE Storage .. we will attemp search NO. {i + 1}"); yield return(1000); DE = DarkElixirStorage.Find()?.FirstOrDefault()?.Location.GetCenter(); if (DE != null) { Log.Warning($"DE Storage found after {i + 1} retries"); break; } } } if (DE != null) { _target = (PointFT)DE; } else { Log.Debug("[Goblin Knife] coundn't locate the target after aligning the base"); Log.Error("Couldn't find DE Storage we will return home"); Surrender(); yield break; } CreateDeployPoints(); Log.Info($"[Goblin Knife] V{Version} Deploy start"); //get troops var deployElements = Deploy.GetTroops(); var clanCastle = deployElements.ExtractOne(u => u.ElementType == DeployElementType.ClanTroops && UserSettings.UseClanTroops); var earthQuakeSpell = deployElements.Extract(u => u.Id == DeployId.Earthquake); var jumpSpell = deployElements.ExtractOne(DeployId.Jump); var giant = deployElements.ExtractOne(DeployId.Giant); var goblin = deployElements.ExtractOne(DeployId.Goblin); var wizard = deployElements.ExtractOne(DeployId.Wizard); var barbarian = deployElements.ExtractOne(DeployId.Barbarian); var archer = deployElements.ExtractOne(DeployId.Archer); var wallbreaker = deployElements.ExtractOne(DeployId.WallBreaker); var ragespell = deployElements.ExtractOne(DeployId.Rage); var healspell = deployElements.ExtractOne(DeployId.Heal); _freezeSpell = deployElements.ExtractOne(DeployId.Freeze); var heroes = deployElements .Extract(u => (UserSettings.UseKing && u.ElementType == DeployElementType.HeroKing) || (UserSettings.UseQueen && u.ElementType == DeployElementType.HeroQueen) || (UserSettings.UseWarden && u.ElementType == DeployElementType.HeroWarden)) .ToList(); //open near to dark elixer with 4 earthquakes if (earthQuakeSpell?.Sum(u => u.Count) >= 4) { foreach (var unit in earthQuakeSpell) { foreach (int t in Deploy.AtPoint(unit, _earthQuakePoint, unit.Count)) { yield return(t); } } } else { _useJump = true; } yield return(1000); if (giant?.Count > 0) { foreach (int t in Deploy.AlongLine(giant, _attackLine.Item1, _attackLine.Item2, 6, 6)) { yield return(t); } } yield return(1000); if (wizard?.Count > 0) { foreach (int t in Deploy.AlongLine(wizard, _attackLine.Item1, _attackLine.Item2, 8, 4)) { yield return(t); } } if (barbarian?.Count > 0) { while (barbarian.Count > 0) { int count = barbarian.Count; Log.Info($"[Goblin Knife] Deploying {barbarian.PrettyName}"); foreach (int t in Deploy.AlongLine(barbarian, _attackLine.Item1, _attackLine.Item2, count, 4)) { yield return(t); } // prevent infinite loop if deploy point is on red if (barbarian.Count != count) { continue; } Log.Warning($"[Goblin Knife] Couldn't deploy {barbarian.PrettyName}"); break; } } if (archer?.Count > 0) { int archerCount = (int)(archer.Count / 2); Log.Info($"[Goblin Knife] Deploying {archer.PrettyName} "); foreach (int t in Deploy.AlongLine(archer, _attackLine.Item1, _attackLine.Item2, archerCount, 4)) { yield return(t); } } yield return(3000); if (ragespell?.Count >= 2) { foreach (int t in Deploy.AtPoint(ragespell, _ragePoint)) { yield return(t); } } if (wallbreaker?.Count > 0) { Log.Info($"[Goblin Knife] send test {wallbreaker.PrettyName} to check for bombs"); foreach (int t in Deploy.AtPoint(wallbreaker, _orgin, 1)) { yield return(t); } } yield return(1000); while (wallbreaker?.Count > 0) { int count = wallbreaker.Count; Log.Info("[Goblin Knife] send wall breakers in groups"); foreach (int t in Deploy.AtPoint(wallbreaker, _orgin, 3)) { yield return(t); } // prevent infinite loop if deploy point is on red if (wallbreaker.Count != count) { continue; } Log.Warning($"[Goblin Knife] Couldn't deploy {wallbreaker.PrettyName}"); break; } while (giant?.Count > 0) { int count = giant.Count; Log.Info($"[Goblin Knife] Deploying {giant.PrettyName} x{count}"); foreach (int t in Deploy.AtPoint(giant, _orgin, count)) { yield return(t); } // prevent infinite loop if deploy point is on red if (giant.Count != count) { continue; } Log.Warning($"[Goblin Knife] Couldn't deploy {giant.PrettyName}"); break; } yield return(1000); while (wizard?.Count > 0) { int count = wizard.Count; Log.Info($"[Goblin Knife] Deploying {wizard}"); foreach (int t in Deploy.AlongLine(wizard, _attackLine.Item1, _attackLine.Item2, 4, 2)) { yield return(t); } // prevent infinite loop if deploy point is on red if (wizard.Count != count) { continue; } Log.Warning($"[Goblin Knife] Couldn't deploy {wizard.PrettyName}"); break; } if (archer?.Count > 0) { Log.Info($"[Goblin Knife] Deploying {archer.PrettyName} "); foreach (int t in Deploy.AlongLine(archer, _attackLine.Item1, _attackLine.Item2, archer.Count, 4)) { yield return(t); } } yield return(1500); if (_useJump == true && jumpSpell?.Count > 0) { foreach (int t in Deploy.AtPoint(jumpSpell, _jumpPoint)) { yield return(t); } } if (healspell?.Count > 0) { foreach (int t in Deploy.AtPoint(healspell, _healPoint)) { yield return(t); } } if (clanCastle?.Count > 0) { Log.Info($"[Goblin Knife] Deploying {clanCastle.PrettyName}"); foreach (int t in Deploy.AtPoint(clanCastle, _orgin)) { yield return(t); } } if (heroes.Any()) { _delay = 1000; foreach (DeployElement hero in heroes.Where(u => u.Count > 0)) { foreach (int t in Deploy.AtPoint(hero, _orgin)) { yield return(t); } } watchHeroes = true; } yield return(_delay); while (goblin?.Count > 0) { int testGoblins = (int)(goblin.Count / 3); Log.Info($"[Goblin Knife] Deploying {goblin.PrettyName} x{testGoblins}"); foreach (int t in Deploy.AtPoint(goblin, _orgin, testGoblins)) { yield return(t); } yield return(2000); int count = goblin.Count; Log.Info($"[Goblin Knife] Deploying {goblin.PrettyName} x{count}"); foreach (int t in Deploy.AtPoint(goblin, _orgin, count)) { yield return(t); } // prevent infinite loop if deploy point is on red if (goblin.Count != count) { continue; } Log.Warning($"[Goblin Knife] Couldn't deploy {goblin.PrettyName}"); break; } //use freeze if inferno is found if (_freezeSpell?.Count > 0) { var infernos = InfernoTower.Find(); // find and watch inferno towers if (infernos != null) { foreach (var inferno in infernos) { inferno.FirstActivated += DropFreeze; inferno.StartWatching(); } } } yield return(200); foreach (int t in Deploy.AtPoint(healspell, _target)) { yield return(t); } foreach (int t in Deploy.AtPoint(ragespell, _target)) { yield return(t); } if (watchHeroes == true) { Deploy.WatchHeroes(heroes, 7000); } }
public override IEnumerable <int> AttackRoutine() { Log.Info("[Breakthrough] Deploy start"); var funnelIds = new[] { DeployId.Archer, DeployId.Barbarian, DeployId.Minion, DeployId.Wizard }; var byLineIds = new[] { DeployId.Archer, DeployId.Barbarian, DeployId.Minion, DeployId.Wizard, DeployId.Balloon, DeployId.Dragon, DeployId.BabyDragon, DeployId.Miner }; var byPointIds = new[] { DeployId.Valkyrie, DeployId.Pekka, DeployId.Witch, DeployId.Goblin, DeployId.Bowler }; // get a list of all deployable units var deployElements = Deploy.GetTroops(); // extract spells into their own list var spells = deployElements.Extract(DeployElementType.Spell); // extract heores into their own list var heroes = deployElements.Extract(u => u.IsHero); // extract clanCastle into its own list var clanCastle = deployElements.ExtractOne(u => u.ElementType == DeployElementType.ClanTroops); // get tanks var tanks = deployElements.Extract(AttackType.Tank).ToArray(); // get wallbreakers var wallBreakers = deployElements.ExtractOne(DeployId.WallBreaker); // get healers var healers = deployElements.ExtractOne(DeployId.Healer); // get funnel troops var funnel = funnelIds.Select(id => deployElements.FirstOrDefault(u => u.Id == id)).Where(u => u != null).ToArray(); // get deploy all in a line var byLine = deployElements.Extract(byLineIds).ToArray(); // get deploy all by point var byPoint = deployElements.Extract(byPointIds).ToArray(); // get hogs var hogs = deployElements.ExtractOne(u => u.Id == DeployId.HogRider); // get heal spells var healSpells = spells.ExtractOne(u => u.Id == DeployId.Heal); // get rage spells var rageSpells = spells.ExtractOne(u => u.Id == DeployId.Rage); // user's wave delay setting var waveDelay = (int)(UserSettings.WaveDelay * 1000); // check if queen walk is an option if (heroes.Any(u => u.Id == DeployId.Queen) && healers?.Count >= 4) { var queen = heroes.ExtractOne(u => u.Id == DeployId.Queen); // get deploy points with queen walk CreateDeployPoints(true); // deploy queen walk Log.Info("[Breakthrough] Queen walk available."); Log.Info($"[Breakthrough] Deploying {queen.PrettyName}"); foreach (var t in Deploy.AtPoint(queen, _qwPoint, waveDelay: waveDelay)) { yield return(t); } var healerCount = Math.Min(healers.Count, 4); Log.Info($"[Breakthrough] Deploying {healers.PrettyName} x{healerCount}"); foreach (var t in Deploy.AtPoint(healers, _healerPoint, healerCount, waveDelay: waveDelay)) { yield return(t); } // watch queen Deploy.WatchHeroes(new List <DeployElement> { queen }); if (rageSpells?.Count > 1) { Log.Info($"[Breakthrough] Deploying {rageSpells.PrettyName} x1"); foreach (var t in Deploy.AtPoint(rageSpells, _queenRagePoint, waveDelay: waveDelay)) { yield return(t); } } // wait 15 seconds yield return(15000); } else { // get deploy points without queen walk CreateDeployPoints(false); } var funnelTank = tanks.FirstOrDefault(u => u.Id == DeployId.Giant) ?? tanks.FirstOrDefault(); // deploy four tanks if available if (funnelTank != null) { var deployCount = Math.Min(funnelTank.Count, 4); Log.Info($"[Breakthrough] Deploying {funnelTank.PrettyName} x{deployCount}"); foreach (var t in Deploy.AlongLine(funnelTank, _attackLine.Item1, _attackLine.Item2, deployCount, deployCount, waveDelay: waveDelay)) { yield return(t); } } // deploy funnel foreach (var unit in funnel.Where(u => u.Count > 0)) { var deployElementCount = Math.Min(unit.Count, UserSettings.WaveSize / unit.UnitData.HousingSpace); Log.Info($"[Breakthrough] Deploying {unit.PrettyName} x{deployElementCount}"); foreach ( var t in Deploy.AlongLine(unit, _attackLine.Item1, _attackLine.Item2, deployElementCount, 4, waveDelay: waveDelay)) { yield return(t); } } // deploy Wallbreakers while (wallBreakers?.Count > 0) { var count = wallBreakers.Count; Log.Info($"[Breakthrough] Deploying {wallBreakers.PrettyName} x3"); foreach (var t in Deploy.AtPoint(wallBreakers, _orgin, 3)) { yield return(t); } // prevent infinite loop if deploy point is on red if (wallBreakers.Count != count) { continue; } Log.Warning($"[Breakthrough] Couldn't deploy {wallBreakers.PrettyName}"); break; } // deploy the rest of the tanks while (tanks.Any(u => u.Count > 0)) { var deployError = false; foreach (var unit in tanks.Where(u => u.Count > 0)) { var count = unit.Count; Log.Info($"[Breakthrough] Deploying {unit.PrettyName} x{unit.Count}"); foreach (var t in Deploy.AtPoint(unit, _orgin, unit.Count, waveDelay: waveDelay)) { yield return(t); } // prevent infinite loop if deploy point is on red if (unit.Count != count) { continue; } Log.Warning($"[Breakthrough] Couldn't deploy {unit.PrettyName}"); deployError = true; break; } if (deployError) { break; } } if (rageSpells?.Count > 0) { Log.Info($"[Breakthrough] Deploying {rageSpells.PrettyName} x1"); foreach (var t in Deploy.AtPoint(rageSpells, _ragePoint, waveDelay: waveDelay)) { yield return(t); } } if (healSpells?.Count > 0) { Log.Info($"[Breakthrough] Deploying {healSpells.PrettyName} x1"); foreach (var t in Deploy.AtPoint(healSpells, _healPoint, waveDelay: waveDelay)) { yield return(t); } } while (byLine.Any(u => u.Count > 0)) { foreach (var unit in byLine.Where(u => u.Count > 0)) { Log.Info($"[Breakthrough] Deploying {unit.PrettyName} x{unit.Count}"); foreach ( var t in Deploy.AlongLine(unit, _attackLine.Item1, _attackLine.Item2, unit.Count, 4, waveDelay: waveDelay)) { yield return(t); } } } while (byPoint.Any(u => u.Count > 0)) { var deployError = false; foreach (var unit in byPoint.Where(u => u.Count > 0)) { var count = unit.Count; Log.Info($"[Breakthrough] Deploying {unit.PrettyName} x{unit.Count}"); foreach (var t in Deploy.AtPoint(unit, _orgin, unit.Count, waveDelay: waveDelay)) { yield return(t); } // prevent infinite loop if deploy point is on red if (unit.Count != count) { continue; } Log.Warning($"[Breakthrough] Couldn't deploy {unit.PrettyName}"); deployError = true; break; } if (deployError) { break; } } if (clanCastle?.Count > 0) { Log.Info($"[Breakthrough] Deploying {clanCastle.PrettyName}"); foreach (var t in Deploy.AtPoint(clanCastle, _orgin, waveDelay: waveDelay)) { yield return(t); } } if (heroes.Any()) { foreach (var hero in heroes.Where(u => u.Count > 0)) { Log.Info($"[Breakthrough] Deploying {hero.PrettyName}"); foreach (var t in Deploy.AtPoint(hero, _orgin, waveDelay: waveDelay)) { yield return(t); } } } if (healers?.Count > 0) { Log.Info($"[Breakthrough] Deploying {healers.PrettyName} x{healers.Count}"); foreach (var t in Deploy.AtPoint(healers, _healerPoint, healers.Count, waveDelay: waveDelay)) { yield return(t); } } if (hogs?.Count > 0) { Log.Info($"[Breakthrough] Deploying {hogs.PrettyName} x{hogs.Count}"); foreach (var t in Deploy.AtPoint(hogs, _orgin, hogs.Count, waveDelay: waveDelay)) { yield return(t); } } Deploy.WatchHeroes(heroes); // get freeze spells _freezeSpell = spells.ExtractOne(u => u.Id == DeployId.Freeze); // no freeze spells so end deployment if (!(_freezeSpell?.Count > 0)) { yield break; } // find and watch inferno towers var infernos = InfernoTower.Find(); foreach (var inferno in infernos) { inferno.FirstActivated += DropFreeze; inferno.StartWatching(); } }
public override IEnumerable <int> AttackRoutine() { int waveLimit = UserSettings.WaveSize; int waveDelay = (int)(UserSettings.WaveDelay * 1000); int heroesIndex = -1; var core = new PointFT(-0.01f, 0.01f); // Points to draw lines in deploy extends area. var topLeft = new PointFT((float)GameGrid.MaxX - 2, (float)GameGrid.DeployExtents.MaxY); var topRight = new PointFT((float)GameGrid.DeployExtents.MaxX, (float)GameGrid.MaxY - 2); var rightTop = new PointFT((float)GameGrid.DeployExtents.MaxX, (float)GameGrid.MinY + 2); var rightBottom = new PointFT((float)GameGrid.MaxX - 2, (float)GameGrid.DeployExtents.MinY); // Move 8 tiles from bottom corner due to unitsbar. var bottomLeft = new PointFT((float)GameGrid.DeployExtents.MinX, (float)GameGrid.MinY + 8); var bottomRight = new PointFT((float)GameGrid.MinX + 8, (float)GameGrid.DeployExtents.MinY); var leftTop = new PointFT((float)GameGrid.MinX + 2, (float)GameGrid.DeployExtents.MaxY); var leftBottom = new PointFT((float)GameGrid.DeployExtents.MinX, (float)GameGrid.MaxY - 2); var linesPointsList = new List <PointFT> { topLeft, topRight, rightTop, rightBottom, bottomLeft, bottomRight, leftBottom, leftTop }; // Main four lines of attack. var topRightLine = new Tuple <PointFT, PointFT>(topRight, rightTop); var bottomRightLine = new Tuple <PointFT, PointFT>(bottomRight, rightBottom); var bottomLeftLine = new Tuple <PointFT, PointFT>(bottomLeft, leftBottom); var topLeftLine = new Tuple <PointFT, PointFT>(topLeft, leftTop); // List of the four attack lines in clocwise order var attackLines = new List <Tuple <PointFT, PointFT> > { topLeftLine, topRightLine, bottomRightLine, bottomLeftLine }; var deployHeroesAt = GetCurrentSetting("Deploy Heroes At"); var target = SmartFourFingersHelper.GetHeroesTarget(deployHeroesAt); var nearestRedPointToTarget = GameGrid.RedPoints.OrderBy(p => p.DistanceSq(target)).FirstOrDefault(); var nearestLinePoint = linesPointsList.OrderBy(p => p.DistanceSq(nearestRedPointToTarget)).FirstOrDefault(); heroesIndex = attackLines.FindIndex(u => (u.Item1.X == nearestLinePoint.X && u.Item1.Y == nearestLinePoint.Y) || (u.Item2.X == nearestLinePoint.X && u.Item2.Y == nearestLinePoint.Y)); var units = Deploy.GetTroops(); var heroes = units.Extract(x => x.IsHero); var cc = units.ExtractOne(u => u.ElementType == DeployElementType.ClanTroops); var spells = units.Extract(u => u.ElementType == DeployElementType.Spell); units.OrderForDeploy(); // Set first attack line // Start from the next line to user defined to end with user defined line var line = attackLines.NextOf(attackLines[heroesIndex]); var index = attackLines.FindIndex(u => u.Item1.X == line.Item1.X && u.Item1.Y == line.Item1.Y); Log.Info($"{AttackName} {Version} starts"); // Start troops deployment on four sides. for (var i = 4; i >= 1; i--) { foreach (var unit in units) { if (unit?.Count > 0) { var count = unit.Count / i; var fingers = count % 4 <= 1 ? count : 4; foreach (var t in Deploy.AlongLine(unit, line.Item1, line.Item2, count, fingers, 0, waveDelay)) { yield return(t); } } } if (i != 1) { line = attackLines.NextOf(attackLines[index]); index = attackLines.FindIndex(u => u.Item1.X == line.Item1.X && u.Item1.Y == line.Item1.Y); } } if (cc?.Count > 0) { Log.Info($"{AttackName} Deploy Clan Castle troops"); foreach (var t in Deploy.AlongLine(cc, line.Item1, line.Item2, 1, 1, 0, waveDelay)) { yield return(t); } } if (heroes.Any()) { Log.Info($"{AttackName} Deploy Heroes"); foreach (var hero in heroes.Where(u => u.Count > 0)) { foreach (var t in Deploy.AlongLine(hero, line.Item1, line.Item2, 1, 1, 0, waveDelay)) { yield return(t); } } Deploy.WatchHeroes(heroes, 5000); } var minDEDrillLevel = GetCurrentSetting("Min Drill Level"); // start smart zap if (GetCurrentSetting("Smart Zap Drills") == 1) { var waitBeforeSmartZap = GetCurrentSetting("Start Zap Drills After ?(sec)") * 1000; var minDEAmount = GetCurrentSetting("Min Dark Elixir per Zap"); yield return(waitBeforeSmartZap); foreach (var t in SmartZapping.SmartZap(minDEAmount, minDEDrillLevel, spells)) { yield return(t); } } // start Use EarthQuake spell on drills if (GetCurrentSetting("Use EarthQuake spell on drills") == 1) { foreach (var t in SmartZapping.UseEQOnDrills(minDEDrillLevel, spells)) { yield return(t); } } // end battle var endBattleTime = GetCurrentSetting("End Battle after zap ?(sec)"); foreach (var t in SmartZapping.EndBattle(endBattleTime)) { yield return(t); } }