public override async Task <TaskRes> Execute(Account acc) { // Sets building task to be built //if (this.Task == null) ConfigNextExecute(acc); if (this.Task == null) { // There is no building task left. Remove the BotTask acc.Tasks.Remove(this); return(TaskRes.Executed); } // Check if the task is complete var(urlId, constructNew) = GetUrlForBuilding(acc, Vill, Task); if (urlId == null) { //no space for this building Vill.Build.Tasks.Remove(this.Task); this.Task = null; return(await Execute(acc)); } // In which dorf is the building. So bot is less suspicious. if (!acc.Wb.CurrentUrl.Contains($"/dorf{((Task.BuildingId ?? default) < 19 ? 1 : 2)}.php")) { string navigateTo = $"{acc.AccInfo.ServerUrl}/"; //Switch village! navigateTo += (Task.BuildingId ?? default) < 19 ? "dorf1.php" : "dorf2.php"; // For localization purposes, bot sends raw http req to Travian servers. // We need localized building names, and JS hides the title of the //buildings on selenium browser. acc.Wb.Html = HttpHelper.SendGetReq(acc, navigateTo); await System.Threading.Tasks.Task.Delay(AccountHelper.Delay()); if (navigateTo.EndsWith("dorf1.php")) { TaskExecutor.UpdateDorf1Info(acc); } else { TaskExecutor.UpdateDorf2Info(acc); // dorf2 ok } Localizations.UpdateLocalization(acc); } // Check if there are already too many buildings currently constructed var maxBuild = 1; if (acc.AccInfo.PlusAccount) { maxBuild++; } if (acc.AccInfo.Tribe == TribeEnum.Romans) { maxBuild++; } if (Vill.Build.CurrentlyBuilding.Count >= maxBuild) { //Execute next upgrade task after currently building this.NextExecute = Vill.Build.CurrentlyBuilding.First().Duration.AddSeconds(3); TaskExecutor.ReorderTaskList(acc); return(TaskRes.Executed); } var url = $"{acc.AccInfo.ServerUrl}/build.php?id={urlId}"; // Fast building for TTWars, only if we have enough resources //if (acc.AccInfo.ServerUrl.Contains("ttwars") && !url.Contains("category") && false) // disabling this //{ // var building = vill.Build.Buildings.FirstOrDefault(x => x.Id == this.task.BuildingId); // var lvl = building.Level; // if (building.UnderConstruction) lvl++; // var storedRes = ResourcesHelper.ResourcesToArray(vill.Res.Stored.Resources); // var neededRes = BuildingsCost.GetBuildingCost(this.task.Building, lvl + 1); // if (ResourcesHelper.EnoughRes(storedRes, neededRes)) // { // //url += "&fastUP=1"; // return TaskRes.Executed; // } //} // Append correct tab if (!constructNew) { switch (this.Task.Building) { case BuildingEnum.RallyPoint: url += "&tt=0"; break; case BuildingEnum.Marketplace: url += "&t=0"; break; case BuildingEnum.Residence: case BuildingEnum.Palace: url += "&s=0"; break; } } await acc.Wb.Navigate(url); var constructContract = acc.Wb.Html.GetElementbyId($"contract_building{(int)Task.Building}"); var upgradeContract = acc.Wb.Html.GetElementbyId("build"); TaskRes response; this.NextExecute = null; if (constructContract != null) { if (!IsEnoughRes(acc, constructContract)) { return(TaskRes.Executed); } response = await Construct(acc, constructContract); } else if (upgradeContract != null) { if (!IsEnoughRes(acc, upgradeContract)) { return(TaskRes.Executed); } response = await Upgrade(acc, upgradeContract); } else { throw new Exception("No contract was found!"); } if (this.NextExecute == null) { ConfigNextExecute(acc); } return(response); }