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 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); } }