/// <summary> /// When new village is found by the bot, it should firstly check barracks, then stable and then workshop, /// to see which troops are researched /// </summary> public override async Task <TaskRes> Execute(Account acc) { var wb = acc.Wb.Driver; // If we have Plus account, just check that. if (acc.AccInfo.PlusAccount) { await VersionHelper.Navigate(acc, "/dorf3.php?s=5&su=2", "/village/statistics/troops?su=2"); OverviewParser.UpdateTroopsLevels(acc.Wb.Html, ref acc); // We have updated all villages at the same time. No need to continue. acc.Tasks.RemoveAll(x => x.GetType() == typeof(UpdateTroops)); return(TaskRes.Executed); } var smithy = Vill.Build.Buildings.FirstOrDefault(x => x.Type == Classificator.BuildingEnum.Smithy); if (smithy != null) { await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?id={smithy.Id}"); Vill.Troops.Levels = TroopsParser.GetTroopLevels(acc.Wb.Html); TroopsHelper.UpdateResearchedTroops(Vill); return(TaskRes.Executed); } for (int i = 0; i < 3; i++) { //var building = GetBuilding(i); //await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?id={building.Id}"); // TODO: parse content } return(TaskRes.Executed); }
// Copied from UpdateTroops BotTask public async Task UpdateTroopsResearchedAndLevels(Account acc) { if (acc.AccInfo.PlusAccount) { // From overview we get all researched troops and their levels switch (acc.AccInfo.ServerVersion) { case Classificator.ServerVersionEnum.T4_4: await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/dorf3.php?s=5&su=2"); break; case Classificator.ServerVersionEnum.T4_5: await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/village/statistics/troops?su=2"); break; } OverviewParser.UpdateTroopsLevels(acc.Wb.Html, ref acc); // We have updated all villages at the same time. No need to continue. acc.Tasks.RemoveAll(x => x.GetType() == typeof(UpdateTroops)); return; } var smithy = Vill.Build.Buildings.FirstOrDefault(x => x.Type == Classificator.BuildingEnum.Smithy); if (smithy != null) { // If smithy exists, we get all researched troops and their levels await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?id={smithy.Id}"); Vill.Troops.Levels = TroopsParser.GetTroopLevels(acc.Wb.Html); TroopsHelper.UpdateResearchedTroops(Vill); return; } }
public bool TroopsCountRecieved(Account acc, int[] troopsAtHome) { // Attack with all offensive troops for (int i = 0; i < 10; i++) { var troop = TroopsHelper.TroopFromInt(acc, i); if (!TroopsData.IsTroopOffensive(troop)) { continue; } base.TroopsMovement.Troops[i] = troopsAtHome[i]; } // Hero if (troopsAtHome.Length == 11 && troopsAtHome[10] == 1) { base.TroopsMovement.Troops[10] = 1; } // Check if we have enough offensive troops to send var upkeep = TroopsHelper.GetTroopsUpkeep(acc, base.TroopsMovement.Troops); if (upkeep < this.Vill.FarmingNonGold.MinTroops) { var log = $"Village {Vill.Name} does not have enough offensive troops to attack the oasis!"; log += $"Required {this.Vill.FarmingNonGold.MinTroops}, but only {upkeep} (crop consumption) "; log += "of off was in the village. Bot won't send the attack."; acc.Wb.Log(log); return(false); } return(true); }
public override async Task <TaskRes> Execute(HtmlDocument htmlDoc, ChromeDriver wb, Files.Models.AccModels.Account acc) { var building = vill.Build.Buildings.FirstOrDefault(x => x.Type == Classificator.BuildingEnum.Marketplace); if (building == null) { //update dorg, no buildingId found? TaskExecutor.AddTask(acc, new UpdateDorf2() { ExecuteAt = DateTime.Now, vill = vill }); Console.WriteLine($"There is no {building} in this village!"); return(TaskRes.Executed); } await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?id={building.Id}&t=5"); //get troop resource/time cost var troopCost = TroopCost.GetResourceCost(TrainTask.Troop, TrainTask.Great); var trainNum = TroopsHelper.TroopsToFill(acc, TargetVill, TrainTask.Troop, TrainTask.Great); //how many troops we can train with resources that we have var mainVillResStored = ResourcesHelper.ResourcesToArray(vill.Res.Stored.Resources); var targetVillStoredRes = ResourcesHelper.ResourcesToArray(TargetVill.Res.Stored.Resources); // Max troops we can train with resources that we have var maxTroopsToTrain = ResourcesHelper.MaxTroopsToTrain(mainVillResStored, targetVillStoredRes, troopCost); // If we don't have enough rsoruces to train the number of troops that we want, we will train max number of troops that we can if (maxTroopsToTrain < trainNum) { trainNum = maxTroopsToTrain; } //calculate how many resources we need to train trainNum of troops long[] neededRes = troopCost.Select(x => x * trainNum).ToArray(); //if we have already enough resources in the target village, no need to send anything if (ResourcesHelper.EnoughRes(targetVillStoredRes, neededRes)) { this.TrainTask.ExecuteAt = DateTime.Now; TaskExecutor.ReorderTaskList(acc); return(TaskRes.Executed); } //amount of resources we want to transit to target village var sendRes = ResourcesHelper.SendAmount(targetVillStoredRes, neededRes); // Check how many merchants we have. If we have 0, wait till some come back. var transitTimespan = await MarketHelper.MarketSendResource(acc, sendRes, TargetVill, this); //train the troops in the target village after we send the needed this.TrainTask.ExecuteAt = DateTime.Now.Add(transitTimespan).AddSeconds(5); TaskExecutor.ReorderTaskList(acc); //TODO: Update marketplace sending return(TaskRes.Executed); }
private void UpdateWorkshop(Account acc, Village vill, CellCollection cells, int column) { var text = cells[column].Text; var troop = (Classificator.TroopsEnum)Enum.Parse(typeof(Classificator.TroopsEnum), text.Replace(" ", "")); if (troop == vill.Settings.WorkshopTrain) return; //no difference vill.Settings.WorkshopTrain = troop; TroopsHelper.ReStartResearchAndImprovement(acc, vill); }
public override async Task <TaskRes> Execute(HtmlDocument htmlDoc, ChromeDriver wb, Files.Models.AccModels.Account acc) { if (vill == null) { vill = AccountHelper.GetMainVillage(acc); } Classificator.BuildingEnum building = (Great == false) ? TroopsHelper.GetTroopBuilding(troop, false) : TroopsHelper.GetTroopBuilding(troop, true); var buildId = vill.Build.Buildings.FirstOrDefault(x => x.Type == building); if (buildId == null) { //update dorf, no buildingId found? TaskExecutor.AddTask(acc, new UpdateDorf2() { ExecuteAt = DateTime.Now }); Console.WriteLine($"There is no {building} in this village!"); return(TaskRes.Executed); } await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?id={buildId.Id}"); var troopNode = htmlDoc.DocumentNode.Descendants("img").FirstOrDefault(x => x.HasClass("u" + (int)troop)); while (!troopNode.HasClass("details")) { troopNode = troopNode.ParentNode; } //finding the correct "Exchange resources" button var exchangeResButton = troopNode.Descendants("button").FirstOrDefault(x => x.HasClass("gold")); wb.ExecuteScript($"document.getElementById('{exchangeResButton.GetAttributeValue("id", "")}').click()"); //Exchange resources button await Task.Delay(AccountHelper.Delay()); htmlDoc.LoadHtml(wb.PageSource); await Task.Delay(AccountHelper.Delay()); var distribute = htmlDoc.DocumentNode.SelectNodes("//*[text()[contains(., 'Distribute remaining resources.')]]")[0]; while (distribute.Name != "button") { distribute = distribute.ParentNode; } string distributeid = distribute.GetAttributeValue("id", ""); wb.ExecuteScript($"document.getElementById('{distributeid}').click()"); //Distribute resources button await Task.Delay(AccountHelper.Delay()); wb.ExecuteScript($"document.getElementById('npc_market_button').click()"); //Exchange resources button return(TaskRes.Executed); }
/// <summary> /// PostTask. Repeats sending resources and training troops. Needs to fill up training above X hours. /// </summary> /// <param name="htmlDoc">html of the page</param> /// <param name="acc">Account</param> public void RepeatTrainingCycle(HtmlDocument htmlDoc, Account acc) { var trainingEnds = TroopsHelper.GetTrainingTimeForBuilding(building, vill); // If sendRes is activated and there are some resources left to send if (vill.Settings.SendRes && MarketHelper.GetResToMainVillage(this.vill).Sum() > 0) { // Check If all troops are filled in this vill before sending resources back to main village if (TroopsHelper.EverythingFilled(acc, vill)) { TaskExecutor.AddTask(acc, new SendResToMain() { vill = this.vill, ExecuteAt = DateTime.MinValue.AddHours(1) }); } } if (vill.Settings.GetRes) { var nextCycle = trainingEnds.AddHours(-acc.Settings.FillInAdvance); if (nextCycle < DateTime.Now) { // Send resources asap. nextCycle = DateTime.MinValue.AddHours(3); } else { TaskExecutor.AddTask(acc, new UpdateDorf1() { ExecuteAt = nextCycle, vill = this.vill }); } TaskExecutor.AddTask(acc, new SendResFillTroops() { ExecuteAt = nextCycle.AddMilliseconds(1), vill = AccountHelper.GetMainVillage(acc), TargetVill = this.vill, TrainTask = this }); this.NextExecute = nextCycle.AddMinutes(30); //will get overwritten in sendResFillTroops TaskExecutor.ReorderTaskList(acc); } else { var later = DateTime.Now.AddMinutes(1); // Don't training again sooner than after 10min if (later > trainingEnds) { trainingEnds = later; } this.NextExecute = trainingEnds; } }
private void UpdateGS(Account acc, Village vill, CellCollection cells, int column) { bool enabled = cells[column].Checked; if (vill.Settings.GreatStableTrain == enabled) return; //no difference vill.Settings.GreatStableTrain = enabled; if (enabled) { if (!TroopsHelper.EverythingFilled(acc, vill)) TroopsHelper.ReStartTroopTraining(acc, vill); } }
public void NewVillage(HtmlDocument htmlDoc, Account acc) { //TODO: parse when the 3rd settler will be trained. var training = TroopsHelper.TrainingDuration(htmlDoc); TaskExecutor.AddTaskIfNotExists(acc, new SendSettlers() { ExecuteAt = training.AddSeconds(3), vill = this.vill, Priority = TaskPriority.Medium }); }
public override async Task <TaskRes> Execute(Account acc) { await base.Execute(acc); if (!await VillageHelper.EnterBuilding(acc, Vill, Classificator.BuildingEnum.Marketplace, "&t=5")) { return(TaskRes.Executed); } //get troop resource/time cost var troopCost = TroopCost.GetResourceCost(TrainTask.Troop, TrainTask.Great); var trainNum = TroopsHelper.TroopsToFill(acc, TargetVill, TrainTask.Troop, TrainTask.Great); //how many troops we can train with resources that we have var mainVillResStored = Vill.Res.Stored.Resources.ToArray(); var targetVillStoredRes = TargetVill.Res.Stored.Resources.ToArray(); // Max troops we can train with resources that we have var maxTroopsToTrain = ResourcesHelper.MaxTroopsToTrain(mainVillResStored, targetVillStoredRes, troopCost); // If we don't have enough rsoruces to train the number of troops that we want, we will train max number of troops that we can if (maxTroopsToTrain < trainNum) { trainNum = maxTroopsToTrain; } //calculate how many resources we need to train trainNum of troops long[] neededRes = troopCost.Select(x => x * trainNum).ToArray(); //if we have already enough resources in the target village, no need to send anything if (ResourcesHelper.IsEnoughRes(targetVillStoredRes, neededRes)) { this.TrainTask.ExecuteAt = DateTime.Now; TaskExecutor.ReorderTaskList(acc); return(TaskRes.Executed); } //amount of resources we want to transit to target village var sendRes = ResourcesHelper.SendAmount(targetVillStoredRes, neededRes); // Check how many merchants we have. If we have 0, wait till some come back. var transitTimespan = await MarketHelper.MarketSendResource(acc, sendRes, TargetVill, this); //train the troops in the target village after we send the needed this.TrainTask.ExecuteAt = DateTime.Now.Add(transitTimespan).AddSeconds(5); TaskExecutor.ReorderTaskList(acc); //TODO: Update marketplace sending return(TaskRes.Executed); }
//TODO add my troops in other villages, with village coords etc //TODO: troops count, troops researched, market stuff public void Init(Account acc) { //TroopsInVillage = new List<TroopsRaw>(); //MyTroops = new List<TroopsRaw>(); CurrentlyTraining = new CurrentlyTraining(); CurrentlyTraining.Init(); Researched = new List <Classificator.TroopsEnum>(); Researched.Add(TroopsHelper.TribeFirstTroop(acc.AccInfo.Tribe)); Levels = new List <TroopLevel>(); ToResearch = new List <Classificator.TroopsEnum>(); ToImprove = new List <Classificator.TroopsEnum>(); }
//Save button private void button1_Click(object sender, EventArgs e) { var acc = GetSelectedAcc(); //change vill names list var changeVillNames = new List <(int, string)>(); for (int i = 0; i < tableModelMain.Rows.Count; i++) { var cells = tableModelMain.Rows[i].Cells; int column = 0; //Village id var id = Int32.Parse(cells[column].Text); var vill = acc.Villages.First(x => x.Id == id); //check if name is different. if it is, change the name var name = cells[++column].Text; if (name != vill.Name) { changeVillNames.Add((id, name)); } column++; UpdateBarracks(acc, vill, cells, column); column++; UpdateGB(acc, vill, cells, column); column++; UpdateStable(acc, vill, cells, column); column++; UpdateGS(acc, vill, cells, column); column++; UpdateWorkshop(acc, vill, cells, column); column++; vill.Settings.AutoImprove = cells[column].Checked; // Reset training if (!TroopsHelper.EverythingFilled(acc, vill) && acc.Tasks != null) { TroopsHelper.ReStartTroopTraining(acc, vill); } } //Change name of village/s if (0 < changeVillNames.Count && acc.Tasks != null) { TaskExecutor.AddTaskIfNotExists(acc, new ChangeVillageName() { ExecuteAt = DateTime.Now, ChangeList = changeVillNames }); } }
public override async Task <TaskRes> Execute(Account acc) { var wb = acc.Wb.Driver; if (Vill == null) { Vill = AccountHelper.GetMainVillage(acc); } await base.Execute(acc); var building = TroopsHelper.GetTroopBuilding(troop, Great); if (!await VillageHelper.EnterBuilding(acc, Vill, building)) { return(TaskRes.Executed); } var troopNode = acc.Wb.Html.DocumentNode.Descendants("img").FirstOrDefault(x => x.HasClass("u" + (int)troop)); while (!troopNode.HasClass("details")) { troopNode = troopNode.ParentNode; } //finding the correct "Exchange resources" button var exchangeResButton = troopNode.Descendants("button").FirstOrDefault(x => x.HasClass("gold")); string script = $"document.getElementById('{exchangeResButton.GetAttributeValue("id", "")}').click()"; await DriverHelper.ExecuteScript(acc, script); var distribute = acc.Wb.Html.DocumentNode.SelectNodes("//*[text()[contains(., 'Distribute remaining resources.')]]")[0]; while (distribute.Name != "button") { distribute = distribute.ParentNode; } string distributeid = distribute.GetAttributeValue("id", ""); wb.ExecuteScript($"document.getElementById('{distributeid}').click()"); //Distribute resources button await Task.Delay(AccountHelper.Delay()); wb.ExecuteScript($"document.getElementById('npc_market_button').click()"); //Exchange resources button return(TaskRes.Executed); }
//You would probably have to take into account ally training bonus, artifacts, helmets, horse fountain... public static TimeSpan GetTrainingTime(Account acc, Village vill, Classificator.TroopsEnum troop, bool great) { var buildingType = TroopsHelper.GetTroopBuilding(troop, great); var building = vill.Build.Buildings.FirstOrDefault(x => x.Type == buildingType); var troopId = (int)troop; if (troopId > 40) { troopId -= 20; //since we don't have values for nature/natars } var baseTime = TrainTime[troopId]; var sec = Math.Pow(0.9, building.Level - 1) * baseTime; var millis = sec % 1; var baseTimespan = new TimeSpan(0, 0, 0, (int)sec, (int)millis * 1000); return(new TimeSpan(baseTimespan.Ticks / acc.AccInfo.ServerSpeed)); }
private string[] GetPossibleTroops(Classificator.BuildingEnum building) { List<string> ret = new List<string>(); ret.Add("None"); var acc = getSelectedAcc(); if (acc.Villages.Count == 0) return ret.ToArray(); //Acc has now been initialised int troopsEnum = ((int)acc.AccInfo.Tribe - 1) * 10; for (var i = troopsEnum + 1; i < troopsEnum + 11; i++) { Classificator.TroopsEnum troop = (Classificator.TroopsEnum)i; if (TroopsHelper.GetTroopBuilding(troop, false) == building) { ret.Add(VillageHelper.EnumStrToString(troop.ToString())); } } return ret.ToArray(); }
private void SendSettlersTask(Account acc) { var training = TroopsHelper.TrainingDuration(acc.Wb.Html); if (training < DateTime.Now) { training = DateTime.Now; } training = training.AddSeconds(5); acc.Wb.Log($"Bot will (try to) send settlers in {TimeHelper.InSeconds(training)} sec"); TaskExecutor.AddTaskIfNotExists(acc, new SendSettlers() { ExecuteAt = training, Vill = this.Vill }); }
private void SendSettlersTask(Account acc) { var training = TroopsHelper.TrainingDuration(acc.Wb.Html); if (training < DateTime.Now) { training = DateTime.Now; } training = training.AddSeconds(5); acc.Wb.Log($"Bot will (try to) send settlers in {TimeHelper.InSeconds(training)} sec"); TaskExecutor.AddTaskIfNotExists(acc, new SendSettlers() { ExecuteAt = training, Vill = this.Vill, // For high speed servers, you want to train settlers asap Priority = 1000 < acc.AccInfo.ServerSpeed ? TaskPriority.High : TaskPriority.Medium, }); }
public override async Task <TaskRes> Execute(Account acc) { // Troops task TroopsHelper.ReStartTroopTraining(acc, Vill); await Task.Delay(AccountHelper.Delay()); TroopsHelper.ReStartResearchAndImprovement(acc, Vill); await Task.Delay(AccountHelper.Delay()); // Building task BuildingHelper.ReStartBuilding(acc, Vill); await Task.Delay(AccountHelper.Delay()); BuildingHelper.ReStartDemolishing(acc, Vill); await Task.Delay(AccountHelper.Delay()); // Celebration task AccountHelper.ReStartCelebration(acc, Vill); return(TaskRes.Executed); }
public bool TroopsCountRecieved(Account acc, int[] troopsAtHome) { int upkeepSent = 0; for (int i = 0; i < 10; i++) { var troop = TroopsHelper.TroopFromInt(acc, i); if (!TroopsData.IsTroopDefensive(troop) || troopsAtHome[i] == 0) { continue; } var upkeep = TroopSpeed.GetTroopUpkeep(troop); int sendAmount = troopsAtHome[i]; int toSend = this.DeffAmount.Amount / upkeep; bool finished = false; if (toSend - upkeepSent < sendAmount) { // If we have enough troops, no other tasks need to be executed this.NextTask = null; finished = true; sendAmount = toSend; } base.TroopsMovement.Troops[i] = sendAmount; upkeepSent += sendAmount * upkeep; if (finished) { break; } } this.DeffAmount.Amount -= upkeepSent; acc.Wb.Log($"Bot will send {upkeepSent} deff (in upkeep) from {this.Vill.Name} to {this.TargetVillage}. Still needed {this.DeffAmount.Amount} deff"); return(true); }
public async Task UpdateTroopsTraining(Account acc) { foreach (var trainingBuilding in trainingBuildings) { if (!await VillageHelper.EnterBuilding(acc, Vill, trainingBuilding)) { continue; } // Mark troops that user can train in building as researched TroopsHelper.UpdateTroopsResearched(Vill, acc.Wb.Html); var ct = TroopsParser.GetTroopsCurrentlyTraining(acc.Wb.Html); switch (trainingBuilding) { case Classificator.BuildingEnum.Barracks: Vill.Troops.CurrentlyTraining.Barracks = ct; break; case Classificator.BuildingEnum.Stable: Vill.Troops.CurrentlyTraining.Stable = ct; break; case Classificator.BuildingEnum.GreatBarracks: Vill.Troops.CurrentlyTraining.GB = ct; break; case Classificator.BuildingEnum.GreatStable: Vill.Troops.CurrentlyTraining.GS = ct; break; case Classificator.BuildingEnum.Workshop: Vill.Troops.CurrentlyTraining.Workshop = ct; break; } await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/dorf2.php"); await Task.Delay(AccountHelper.Delay()); } }
private string[] GetPossibleTroops(Classificator.BuildingEnum building) { List <string> ret = new List <string>(); ret.Add("None"); var acc = GetSelectedAcc(); if (acc.Villages.Count == 0) { return(ret.ToArray()); //Acc has now been initialised } var tribes = new List <Classificator.TribeEnum>(5); if (NYS.Checked) { tribes.Add(Classificator.TribeEnum.Egyptians); tribes.Add(Classificator.TribeEnum.Gauls); tribes.Add(Classificator.TribeEnum.Huns); tribes.Add(Classificator.TribeEnum.Romans); tribes.Add(Classificator.TribeEnum.Teutons); } else { tribes.Add(acc.AccInfo.Tribe ?? Classificator.TribeEnum.Any); } foreach (var tribe in tribes) { int troopsEnum = ((int)tribe - 1) * 10; for (var i = troopsEnum + 1; i < troopsEnum + 11; i++) { Classificator.TroopsEnum troop = (Classificator.TroopsEnum)i; if (TroopsHelper.GetTroopBuilding(troop, false) == building) { ret.Add(VillageHelper.EnumStrToString(troop.ToString())); } } } return(ret.ToArray()); }
public override async Task <TaskRes> Execute(Account acc) { TaskExecutor.RemoveSameTasksForVillage(acc, Vill, typeof(UpdateDorf1), this); TaskExecutor.RemoveSameTasksForVillage(acc, Vill, typeof(UpdateDorf2), this); await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/dorf1.php"); // Update dorf1 await Task.Delay(AccountHelper.Delay()); await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/dorf2.php"); // Update dorf2 // On new village import the building tasks if (ImportTasks && !string.IsNullOrEmpty(acc.NewVillages.BuildingTasksLocationNewVillage)) { IoHelperCore.AddBuildTasksFromFile(acc, Vill, acc.NewVillages.BuildingTasksLocationNewVillage); } await UpdateTroopsResearchedAndLevels(acc); await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/dorf2.php"); await Task.Delay(AccountHelper.Delay()); await UpdateTroopsTraining(acc); var firstTroop = TroopsHelper.TribeFirstTroop(acc.AccInfo.Tribe); Vill.Troops.TroopToTrain = firstTroop; Vill.Troops.Researched.Add(firstTroop); if (await VillageHelper.EnterBuilding(acc, Vill, Classificator.BuildingEnum.TownHall)) { // Village has town hall, parse celebration duration Vill.Expansion.CelebrationEnd = TimeParser.GetCelebrationTime(acc.Wb.Html); } return(TaskRes.Executed); }
public override async Task <TaskRes> Execute(HtmlDocument htmlDoc, ChromeDriver wb, Files.Models.AccModels.Account acc) { await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?tt=2&id=39"); int[] troopsAtHome = TroopsMovementParser.GetTroopsInRallyPoint(htmlDoc); for (int i = 0; i < 10; i++) { var troop = TroopsHelper.TroopFromInt(acc, i); if (TroopsHelper.IsTroopDefensive(troop)) { var upkeep = TroopSpeed.GetTroopUpkeep(troop); int sendAmount = troopsAtHome[i]; if (this.DeffAmount.DeffCount != null) { if (sendAmount * upkeep > this.DeffAmount.DeffCount) { // We have sent all needed deff sendAmount = (this.DeffAmount.DeffCount ?? 0) / upkeep; // Remove all other (linked) SendDeff bot tasks var list = new List <SendDeff> { this.NextDeffTask }; while (list.Last() != null) { list.Add(list.Last().NextDeffTask); } foreach (var task in list) { if (task == null) { continue; } acc.Tasks.Remove(task); } } else { this.DeffAmount.DeffCount -= sendAmount * upkeep; } } wb.ExecuteScript($"document.getElementsByName('t{i + 1 }')[0].value='{sendAmount}'"); } } //select coordinates wb.ExecuteScript($"document.getElementById('xCoordInput').value='{TargetVillage.x}'"); wb.ExecuteScript($"document.getElementById('yCoordInput').value='{TargetVillage.y}'"); await Task.Delay(AccountHelper.Delay()); //Select reinforcement string script = "var radio = document.getElementsByClassName(\"radio\");for(var i = 0; i < radio.length; i++){"; script += $"if(radio[i].value == '2') radio[i].checked = \"checked\"}}"; wb.ExecuteScript(script); await Task.Delay(2 *AccountHelper.Delay()); wb.ExecuteScript($"document.getElementById('btn_ok').click()"); await Task.Delay(2 *AccountHelper.Delay()); // Confirm wb.ExecuteScript($"document.getElementById('btn_ok').click()"); //Click send return(TaskRes.Executed); }
public override async Task <TaskRes> Execute(HtmlDocument htmlDoc, ChromeDriver wb, Files.Models.AccModels.Account acc) { await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?tt=2&id=39"); var wavesReady = new List <WaveReadyModel>(); // Get request time for getting more accurate attacks Ping ping = new Ping(); PingReply reply = ping.Send(IoHelperCore.UrlRemoveHttp(acc.AccInfo.ServerUrl)); var reqTripMs = (int)(reply.RoundtripTime / 2); Random rnd = new Random(); // Prepare the waves for (int i = 0; i < SendWaveModels.Count; i++) { Console.WriteLine(DateTime.Now + "Send wave 1"); await Task.Delay(rnd.Next(800, 1000)); var htmlDoc1 = await HttpHelper.SendGetReq(acc, "/build.php?tt=2&id=39"); var build = htmlDoc1.GetElementbyId("build"); var ajaxToken = await HttpHelper.GetAjaxToken(wb); var values = new Dictionary <string, string> { { "dname", "" }, // Name of the village, empty. Bot uses coordinates { "x", SendWaveModels[i].Coordinates.x.ToString() }, { "y", SendWaveModels[i].Coordinates.y.ToString() }, { "c", ((int)SendWaveModels[i].MovementType).ToString() }, // 2 = reinformance, 3 = attack, 4 = raid { "s1", "ok" }, { "ajaxToken", ajaxToken } }; foreach (var hidden in hiddenFields) { var value = build.Descendants("input").FirstOrDefault(x => x.GetAttributeValue("name", "") == hidden).GetAttributeValue("value", ""); values.Add(hidden, value); } // Get available troops int[] troopsAtHome = TroopsMovementParser.GetTroopsInRallyPoint(htmlDoc1); // Send all off dirty hack if (SendWaveModels[i].AllOff) { for (int j = 0; j < 10; j++) { var troop = TroopsHelper.TroopFromInt(acc, j); if (TroopsHelper.IsTroopOffensive(troop) || TroopsHelper.IsTroopRam(troop)) { SendWaveModels[i].Troops[j] = troopsAtHome[j]; troopsAtHome[j] = 0; } } } // Send fake attack dirty hack if (SendWaveModels[i].FakeAttack) { for (int j = 0; j < 10; j++) { if (troopsAtHome[j] > 19) { SendWaveModels[i].Troops[j] = 19; troopsAtHome[j] -= 19; break; } } } for (int j = 0; j < SendWaveModels[i].Troops.Length; j++) { values.Add($"t{j + 1}", SendWaveModels[i].Troops[j].ToString()); } var content = new FormUrlEncodedContent(values); await Task.Delay(rnd.Next(800, 1000)); var ret = await HttpHelper.SendPostReq(acc, content, "/build.php?tt=2&id=39"); var htmlDoc2 = new HtmlAgilityPack.HtmlDocument(); htmlDoc2.LoadHtml(ret); // Get time it takes for troops to the target, for later usage var timespan = TroopsMovementParser.GetTimeOfMovement(htmlDoc2); lastArriveAt = TroopsMovementParser.GetArrivalTime(htmlDoc2); if (timeDifference == TimeSpan.Zero) { var serverTime = TimeParser.GetServerTime(htmlDoc2); timeDifference = DateTime.Now - serverTime; // Negate seconds and milliseconds in time difference. var negateMillis = timeDifference.Milliseconds; negateMillis += timeDifference.Seconds * 1000; timeDifference = timeDifference.Subtract(new TimeSpan(0, 0, 0, 0, negateMillis)); var executeTime = CorrectExecuteTime(timespan); if (DateTime.Now.AddMinutes(1) < executeTime) { // Restart this task at the correct time this.NextExecute = executeTime; return(TaskRes.Executed); } } //var ajaxToken = await HttpHelper.GetAjaxToken(wb); var values2 = new Dictionary <string, string> { { "s1", "ok" }, }; // Copy all hidden names and values var build2 = htmlDoc2.GetElementbyId("build"); var hiddens2 = build2.Descendants("input").Where(x => x.GetAttributeValue("type", "") == "hidden"); foreach (var hidden2 in hiddens2) { var val = hidden2.GetAttributeValue("value", ""); var name = hidden2.GetAttributeValue("name", ""); values2.Add(name, val); } // Add catapult targets values2.TryGetValue("t8", out string cataCount); if (int.Parse(cataCount) > 0) { values2.Add("ctar1", "99"); // 99 = Random, 1 = woodcuter, 2 = claypit.. values2.Add("ctar2", "99"); // 99 = Random } wavesReady.Add(new WaveReadyModel { Content = new FormUrlEncodedContent(values2), MovementTime = timespan }); this.DurationCounter = 0; Console.WriteLine(DateTime.Now + "Send wave 2"); } var waitMs = 1000 - DateTime.Now.Millisecond - reqTripMs; if (waitMs < 0) { waitMs += 1000; } var wait = new TimeSpan(0, 0, 0, 0, waitMs); // Calculate how much you need to wait so waves will arrive at correct time! var targetArrival = SendWaveModels.FirstOrDefault(x => x.Arrival != DateTime.MinValue).Arrival; TimeSpan waitForTarget = (targetArrival - lastArriveAt); if (waitForTarget > TimeSpan.Zero) { var waitForTargetSec = waitForTarget.Seconds + (waitForTarget.Minutes * 60) - 1; // -1 to compensate var waitForTargetTimeSpan = new TimeSpan(0, 0, waitForTargetSec); wait = wait.Add(waitForTargetTimeSpan); this.DurationCounter = -(int)(wait.TotalSeconds * 2); } await Task.Delay(wait); // Send the waves for (int i = 0; i < wavesReady.Count; i++) { // Wait +- 10% selected delay var delay = SendWaveModels[i].DelayMs; var delay10Percent = (int)delay / 10; await Task.Delay(rnd.Next(delay - delay10Percent, delay + delay10Percent)); _ = HttpHelper.SendPostReq(acc, wavesReady[i].Content, "/build.php?tt=2&id=39"); this.DurationCounter = 0; } await Task.Delay(AccountHelper.Delay() * 2); acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?gid=16&tt=1&filter=2&subfilters=4"); //Todo: check waves? return(TaskRes.Executed); }
private async void NewTick() { // Dirty hack. TODO fix the code, so building/troops filling tasks won't fail by themselves restartTasksCounter++; if (restartTasksCounter > 7200) { restartTasksCounter = 0; foreach (var vill in acc.Villages) { if (!TroopsHelper.EverythingFilled(acc, vill)) { TroopsHelper.ReStartTroopTraining(acc, vill); } BuildingHelper.ReStartBuilding(acc, vill); } } if (acc.Tasks.Count == 0) { return; //No tasks } // Another task is already in progress. wait var taskInProgress = acc.Tasks.FirstOrDefault(x => x.Stage != TaskStage.Start); if (taskInProgress != null) { if (taskInProgress.DurationCounter++ > 30) //after 20sec try to re-execute the task { Console.WriteLine($"Task {taskInProgress} timed out. Restarting it.."); taskInProgress.DurationCounter = 15; taskInProgress.Stage = TaskStage.Start; //re-navigate & execute //We have tried re-executing the task 3 times already, something is clearly wrong. Just delete the task. if (++taskInProgress.RetryCounter > 3) { acc.Tasks.Remove(taskInProgress); } } return; } var tasks = acc.Tasks.Where(x => x.ExecuteAt <= DateTime.Now).ToList(); if (tasks.Count == 0) { return; // No tasks yet } BotTask firstTask = tasks.FirstOrDefault(x => x.Priority == TaskPriority.High); if (firstTask == null) { firstTask = tasks.FirstOrDefault(x => x.Priority == TaskPriority.Medium); } if (firstTask == null) { firstTask = tasks.FirstOrDefault(); } //Console.WriteLine($"---Tasks: {acc.Tasks.Count}, first one {firstTask.GetType()}"); if (firstTask.Stage != TaskStage.Start) { return; } //If correct village is selected, otherwise change village if (firstTask.vill != null) { var active = acc.Villages.FirstOrDefault(x => x.Active); if (active != null) //error handling { if (firstTask.vill != active && firstTask.GetType() != typeof(SwitchVillage)) { //wrong village selected, reselect village TaskExecutor.AddTask(acc, new SwitchVillage() { vill = firstTask.vill, Priority = TaskPriority.High }); return; } } } firstTask.Stage = TaskStage.Executing; _ = TaskExecutor.Execute(acc, firstTask); }
public static bool IsTroopOffensive(Account acc, int i) => IsTroopOffensive(TroopsHelper.TroopFromInt(acc, i));
public override async Task <TaskRes> Execute(Account acc) { var wb = acc.Wb.Driver; await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?tt=2&id=39"); var wavesReady = new List <WaveReadyModel>(); // Get request time for getting more accurate attacks Ping ping = new Ping(); PingReply reply = ping.Send(IoHelperCore.UrlRemoveHttp(acc.AccInfo.ServerUrl)); var reqTripMs = (int)(reply.RoundtripTime / 2); Random rnd = new Random(); // Prepare the waves for (int i = 0; i < SendWaveModels.Count; i++) { await Task.Delay(rnd.Next(800, 1000)); var htmlDoc1 = HttpHelper.SendGetReq(acc, "/build.php?tt=2&id=39"); var build = htmlDoc1.GetElementbyId("build"); var req = new RestRequest { Resource = "/build.php?tt=2&id=39", Method = Method.POST, }; req.AddParameter("dname", ""); req.AddParameter("x", SendWaveModels[i].Coordinates.x.ToString()); req.AddParameter("y", SendWaveModels[i].Coordinates.y.ToString()); req.AddParameter("c", ((int)SendWaveModels[i].MovementType).ToString()); req.AddParameter("s1", "ok"); foreach (var hidden in hiddenFields) { var value = build.Descendants("input").FirstOrDefault(x => x.GetAttributeValue("name", "") == hidden); if (value == null) { continue; } req.AddParameter(hidden, value.GetAttributeValue("value", "")); } // Get available troops int[] troopsAtHome = TroopsMovementParser.GetTroopsInRallyPoint(htmlDoc1); // Send all off dirty hack if (SendWaveModels[i].AllOff) { for (int j = 0; j < 10; j++) { var troop = TroopsHelper.TroopFromInt(acc, j); if (TroopsHelper.IsTroopOffensive(troop) || TroopsHelper.IsTroopRam(troop)) { SendWaveModels[i].Troops[j] = troopsAtHome[j]; troopsAtHome[j] = 0; } } } // Send fake attack dirty hack if (SendWaveModels[i].FakeAttack) { for (int j = 0; j < 10; j++) { if (troopsAtHome[j] > 19) { SendWaveModels[i].Troops[j] = 19; troopsAtHome[j] -= 19; break; } } } for (int j = 0; j < SendWaveModels[i].Troops.Length; j++) { switch (acc.AccInfo.ServerVersion) { case Classificator.ServerVersionEnum.T4_4: req.AddParameter($"t{j + 1}", TroopCount(SendWaveModels[i].Troops[j])); break; case Classificator.ServerVersionEnum.T4_5: req.AddParameter($"troops[0][t{j + 1}]", TroopCount(SendWaveModels[i].Troops[j])); break; } } await Task.Delay(rnd.Next(800, 1000)); var ret = HttpHelper.SendPostReq(acc, req); var htmlDoc2 = new HtmlAgilityPack.HtmlDocument(); htmlDoc2.LoadHtml(ret); // Get time it takes for troops to the target, for later usage var timespan = TroopsMovementParser.GetTimeOfMovement(htmlDoc2); lastArriveAt = TroopsMovementParser.GetArrivalTime(htmlDoc2); if (timeDifference == TimeSpan.Zero) { var serverTime = TimeParser.GetServerTime(htmlDoc2); timeDifference = DateTime.Now - serverTime; // Negate seconds and milliseconds in time difference. var negateMillis = timeDifference.Milliseconds; negateMillis += timeDifference.Seconds * 1000; timeDifference = timeDifference.Subtract(new TimeSpan(0, 0, 0, 0, negateMillis)); var executeTime = CorrectExecuteTime(timespan); if (DateTime.Now.AddMinutes(2) < executeTime) { // Restart this task at the correct time this.NextExecute = executeTime; return(TaskRes.Executed); } } //var ajaxToken = await HttpHelper.GetAjaxToken(wb); var req2 = new RestRequest { Resource = "/build.php?tt=2&id=39", Method = Method.POST, }; req2.AddParameter("s1", "ok"); // Copy all hidden names and values var build2 = htmlDoc2.GetElementbyId("build"); var hiddens2 = build2.Descendants("input").Where(x => x.GetAttributeValue("type", "") == "hidden"); foreach (var hidden2 in hiddens2) { var val = hidden2.GetAttributeValue("value", ""); var name = hidden2.GetAttributeValue("name", ""); req2.AddParameter(name, val); } // Add catapult targets string cataCount = "0"; switch (acc.AccInfo.ServerVersion) { case Classificator.ServerVersionEnum.T4_4: cataCount = req2.Parameters.FirstOrDefault(x => x.Name == "t8").Value.ToString(); break; case Classificator.ServerVersionEnum.T4_5: cataCount = req2.Parameters.FirstOrDefault(x => x.Name == "troops[0][t8]").Value.ToString(); // If T4.5, we need to get value "a" as well - From Confirm button var button = htmlDoc2.GetElementbyId("btn_ok"); string a = button.GetAttributeValue("value", ""); req2.AddParameter("a", a); break; } if (int.Parse(cataCount) > 0) { req2.AddParameter("ctar1", "99"); // 99 = Random, 1 = woodcuter, 2 = claypit.. req2.AddParameter("ctar2", "99"); // 99 = Random } wavesReady.Add(new WaveReadyModel { Request = req2, MovementTime = timespan }); } var waitMs = 1000 - DateTime.Now.Millisecond - reqTripMs; if (waitMs < 0) { waitMs += 1000; } var wait = new TimeSpan(0, 0, 0, 0, waitMs); // Calculate how much you need to wait so waves arrive at the correct time! var targetArrival = SendWaveModels.FirstOrDefault(x => x.Arrival != DateTime.MinValue).Arrival; TimeSpan waitForTarget = (targetArrival - lastArriveAt); if (waitForTarget > TimeSpan.Zero) { var waitForTargetSec = waitForTarget.Seconds + (waitForTarget.Minutes * 60) - 1; // -1 to compensate var waitForTargetTimeSpan = new TimeSpan(0, 0, waitForTargetSec); wait = wait.Add(waitForTargetTimeSpan); } await Task.Delay(wait); // Send the waves for (int i = 0; i < wavesReady.Count; i++) { // Wait +- 10% selected delay var delay = SendWaveModels[i].DelayMs; var delay10Percent = (int)delay / 10; await Task.Delay(rnd.Next(delay - delay10Percent, delay + delay10Percent)); _ = HttpHelper.SendPostReq(acc, wavesReady[i].Request); } acc.Wb.Log($"Successfully sent {wavesReady.Count} waves!"); await Task.Delay(AccountHelper.Delay() * 2); await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?gid=16&tt=1&filter=2&subfilters=4"); //Todo: check waves? return(TaskRes.Executed); }
public override async Task <TaskRes> Execute(Account acc) { building = TroopsHelper.GetTroopBuilding(Troop, Great); // Switch hero helmet. If hero will be switched, this TrainTroops task // will be executed right after the hero helmet switch if (HeroHelper.SwitchHelmet(acc, this.Vill, building, this)) { return(TaskRes.Executed); } await base.Execute(acc); if (!await VillageHelper.EnterBuilding(acc, Vill, building)) { return(TaskRes.Executed); } if (this.UpdateOnly || this.Troop == TroopsEnum.None) { return(TaskRes.Executed); } (TimeSpan dur, Resources cost) = TroopsParser.GetTrainCost(acc.Wb.Html, this.Troop); var troopNode = acc.Wb.Html.DocumentNode.Descendants("img").FirstOrDefault(x => x.HasClass("u" + (int)Troop)); if (troopNode == null) { acc.Wb.Log($"Bot tried to train {Troop} in {Vill.Name}, but couldn't find it in {building}! Are you sure you have {Troop} researched?"); return(TaskRes.Executed); } while (!troopNode.HasClass("details")) { troopNode = troopNode.ParentNode; } var inputName = troopNode.Descendants("input").FirstOrDefault().GetAttributeValue("name", ""); long maxNum = 0; switch (acc.AccInfo.ServerVersion) { case ServerVersionEnum.T4_4: maxNum = Parser.RemoveNonNumeric( troopNode.ChildNodes .FirstOrDefault(x => x.Name == "a")?.InnerText ?? "0" ); break; case ServerVersionEnum.T4_5: maxNum = Parser.RemoveNonNumeric( troopNode.ChildNodes .First(x => x.HasClass("cta")) .ChildNodes .First(x => x.Name == "a") .InnerText); break; } if (!HighSpeedServer) { var trainNum = TroopsHelper.TroopsToFill(acc, Vill, this.Troop, this.Great); // Don't train too many troops, just fill up the training building if (maxNum > trainNum) { maxNum = trainNum; } } if (maxNum < 0) { // We have already enough troops in training. return(TaskRes.Executed); } acc.Wb.Driver.ExecuteScript($"document.getElementsByName('{inputName}')[0].value='{maxNum}'"); await Task.Delay(100); await DriverHelper.ExecuteScript(acc, "document.getElementsByName('s1')[0].click()"); UpdateCurrentlyTraining(acc.Wb.Html, acc); if (!HighSpeedServer) { RepeatTrainingCycle(acc.Wb.Html, acc); } return(TaskRes.Executed); }
public override async Task <TaskRes> Execute(HtmlDocument htmlDoc, ChromeDriver wb, Files.Models.AccModels.Account acc) { building = TroopsHelper.GetTroopBuilding(Troop, Great); var buildId = vill.Build.Buildings.FirstOrDefault(x => x.Type == building); if (buildId == null) { //update dorf, no buildingId found? TaskExecutor.AddTask(acc, new UpdateDorf2() { ExecuteAt = DateTime.Now, vill = vill }); Console.WriteLine($"There is no {building} in this village!"); return(TaskRes.Executed); } await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?id={buildId.Id}"); //after finishing task, update currently training this.PostTaskCheck.Add(UpdateCurrentlyTraining); if (!HighSpeedServer) { this.PostTaskCheck.Add(RepeatTrainingCycle); } if (this.UpdateOnly || this.Troop == TroopsEnum.None) { return(TaskRes.Executed); } (TimeSpan dur, Resources cost) = TroopsParser.GetTrainCost(htmlDoc, this.Troop); var troopNode = htmlDoc.DocumentNode.Descendants("img").FirstOrDefault(x => x.HasClass("u" + (int)Troop)); while (!troopNode.HasClass("details")) { troopNode = troopNode.ParentNode; } var inputName = troopNode.Descendants("input").FirstOrDefault().GetAttributeValue("name", ""); var maxNum = Parser.RemoveNonNumeric(troopNode.ChildNodes.FirstOrDefault(x => x.Name == "a").InnerText); if (!HighSpeedServer) { var trainNum = TroopsHelper.TroopsToFill(acc, vill, this.Troop, this.Great); // Don't train too many troops, just fill up the training building if (maxNum > trainNum) { maxNum = trainNum; } } if (maxNum < 0) { // We have already enough troops in training. return(TaskRes.Executed); } wb.ExecuteScript($"document.getElementsByName('{inputName}')[0].value='{maxNum}'"); await Task.Delay(100); wb.ExecuteScript("document.getElementsByName('s1')[0].click()"); //Train button return(TaskRes.Executed); }
public override async Task <TaskRes> Execute(Account acc) { var building = Vill.Build.Buildings .FirstOrDefault(x => x.Type == Classificator.BuildingEnum.Residence || x.Type == Classificator.BuildingEnum.Palace || x.Type == Classificator.BuildingEnum.CommandCenter ); if (!await VillageHelper.EnterBuilding(acc, Vill, building, "&s=1")) { return(TaskRes.Executed); } var settler = TroopsData.TribeSettler(acc.AccInfo.Tribe); var troopNode = acc.Wb.Html.DocumentNode.Descendants("img").FirstOrDefault(x => x.HasClass("u" + (int)settler)); if (troopNode == null) { acc.Wb.Log("No new settler can be trained, probably because 3 settlers are already (being) trained"); SendSettlersTask(acc); return(TaskRes.Executed); } while (!troopNode.HasClass("details")) { troopNode = troopNode.ParentNode; } var maxNum = Parser.RemoveNonNumeric(troopNode.ChildNodes.First(x => x.Name == "a").InnerText); var available = TroopsParser.ParseAvailable(troopNode); var costNode = acc.Wb.Html.DocumentNode.Descendants("div").FirstOrDefault(x => x.HasClass("resourceWrapper")); var cost = ResourceParser.GetResourceCost(costNode); if (!ResourcesHelper.IsEnoughRes(Vill, cost.ToArray())) { ResourcesHelper.NotEnoughRes(acc, Vill, cost, this); return(TaskRes.Executed); } acc.Wb.Driver.ExecuteScript($"document.getElementsByName('t10')[0].value='{maxNum}'"); await Task.Delay(AccountHelper.Delay()); // Click Train button await TbsCore.Helpers.DriverHelper.ExecuteScript(acc, "document.getElementById('s1').click()"); Vill.Troops.Settlers = (int)available + (int)maxNum; var training = TroopsHelper.TrainingDuration(acc.Wb.Html); if (training < DateTime.Now) { training = DateTime.Now; } if (Vill.Troops.Settlers < 3) { //In 1 minute, do the same task (to get total of 3 settlers) this.NextExecute = training.AddSeconds(3); } else { if (acc.NewVillages.AutoSettleNewVillages) { SendSettlersTask(acc); } } return(TaskRes.Executed); }