예제 #1
0
        public async Task <bool> TTWarsTryFastUpgrade(Account acc, string url)
        {
            var building = Vill.Build.Buildings.FirstOrDefault(x => x.Id == this.Task.BuildingId);
            var lvl      = building.Level;

            if (building.UnderConstruction)
            {
                lvl++;
            }

            var neededRes = BuildingsData.GetBuildingCost(building.Type, lvl + 1);

            if (ResourcesHelper.IsEnoughRes(Vill, neededRes) &&
                lvl != 0 &&
                lvl < Task.Level)
            {
                await acc.Wb.Navigate(url + "&fastUP=1");

                CheckIfTaskFinished(++lvl);

                acc.Wb.Log($"Started (fast) upgrading {building.Type} to level {lvl} in {this.Vill?.Name}");

                await PostTaskCheckDorf(acc);

                ConfigNextExecute(acc);
                return(true);
            }

            return(false);
        }
예제 #2
0
        public static bool EnoughResForCelebration(Village vill, bool big)
        {
            var cost = CelebrationCost(big);
            var res  = vill.Res.Stored.Resources.ToArray();

            return(ResourcesHelper.IsEnoughRes(res, cost));
        }
예제 #3
0
        //If Troop == null, just update the troop levels
        public override async Task <TaskRes> Execute(Account acc)
        {
            await base.Execute(acc); // Navigate to dorf2

            if (!await VillageHelper.EnterBuilding(acc, Vill, Classificator.BuildingEnum.Academy))
            {
                return(TaskRes.Executed);
            }

            var troop = Vill.Troops.ToResearch.FirstOrDefault();

            if (troop == TroopsEnum.None)
            {
                return(TaskRes.Executed);                          //We have researched all troops that were on the list
            }
            var troopNode = acc.Wb.Html.DocumentNode.Descendants("img").FirstOrDefault(x => x.HasClass("u" + (int)troop));

            if (troopNode == null)
            {
                acc.Wb.Log($"Researching {troop} was not possible! Bot assumes you already have it researched");
                Vill.Troops.Researched.Add(troop);
                return(TaskRes.Retry);
            }
            while (!troopNode.HasClass("research"))
            {
                troopNode = troopNode.ParentNode;
            }

            var button = troopNode.Descendants("button").FirstOrDefault(x => x.HasClass("green"));

            if (button == null)
            {
                RepeatTask(Vill, troop, DateTime.Now);
            }
            (TimeSpan dur, Resources cost) = TroopsParser.AcademyResearchCost(acc.Wb.Html, troop);

            // Check if we have enough resources to research the troop
            if (!ResourcesHelper.IsEnoughRes(Vill, cost.ToArray()))
            {
                ResourcesHelper.NotEnoughRes(acc, Vill, cost, this);
                return(TaskRes.Executed);
            }

            await DriverHelper.ClickById(acc, button.Id);

            var executeNext = DateTime.Now.Add(dur).AddMilliseconds(10 * AccountHelper.Delay());

            if (Vill.Settings.AutoImprove)
            {
                TaskExecutor.AddTask(acc, new ImproveTroop()
                {
                    Vill = this.Vill, ExecuteAt = DateTime.Now.Add(dur)
                });
            }

            RepeatTask(Vill, troop, executeNext);

            return(TaskRes.Executed);
        }
예제 #4
0
        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);
        }
예제 #5
0
        /// <summary>
        /// Checks if we have enough resources to build the building. If we don't have enough resources,
        /// method sets NextExecute DateTime.
        /// </summary>
        /// <param name="node">Node of the contract</param>
        /// <returns>Whether we have enough resources</returns>
        private bool IsEnoughRes(Account acc, HtmlNode node)
        {
            var resWrapper = node.Descendants().FirstOrDefault(x => x.HasClass("resourceWrapper"));
            var cost       = ResourceParser.GetResourceCost(resWrapper).ToArray();

            // We have enough resources, go on and build it
            if (ResourcesHelper.IsEnoughRes(Vill.Res.Stored.Resources.ToArray(), cost))
            {
                return(true);
            }

            ResourcesHelper.NotEnoughRes(acc, Vill, cost, this, this.Task);

            return(false);
        }
예제 #6
0
        public override async Task <TaskRes> Execute(Account acc)
        {
            // Check if the account has enough culture points
            if (acc.AccInfo.CulturePoints.MaxVillages <= acc.AccInfo.CulturePoints.VillageCount)
            {
                // TODO: this shouldn't be here?
                acc.Wb.Log("Don't have enough culture points");
                this.Vill.Expansion.ExpansionAvailable = true;
                return(TaskRes.Executed);
            }

            if (acc.NewVillages.Locations.Count == 0)
            {
                if (acc.NewVillages.AutoFindVillages) // Find new village to settle
                {
                    TaskExecutor.AddTaskIfNotExists(acc, new FindVillageToSettle()
                    {
                        Vill      = AccountHelper.GetMainVillage(acc),
                        ExecuteAt = DateTime.MinValue.AddHours(10),
                        Priority  = TaskPriority.High
                    });
                    this.NextExecute = DateTime.MinValue.AddHours(11);
                }

                return(TaskRes.Executed);
            }

            await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/karte.php");

            await Task.Delay(AccountHelper.Delay() * 3);

            var newVillage = acc.NewVillages.Locations.FirstOrDefault();

            //acc.NewVillage.NewVillages.Remove(coords); //remove it after settling and changing the vill name??
            string kid = MapHelper.KidFromCoordinates(newVillage.Coordinates, acc).ToString();

            string url = $"{acc.AccInfo.ServerUrl}/build.php?id=39&tt=2";

            switch (acc.AccInfo.ServerVersion)
            {
            case Classificator.ServerVersionEnum.T4_4:
                // https://low4.ttwars.com/build.php?id=39&tt=2&kid=7274&a=6
                url += $"&kid={kid}&a=6";
                break;

            case Classificator.ServerVersionEnum.T4_5:
                // https://tx3.travian.com/build.php?id=39&tt=2&mapid=123&s=1&gid=16
                url += $"&mapid={kid}&s=1&gid=16";
                break;
            }
            await acc.Wb.Navigate(url);

            // Check if we have enough resource
            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);
            }

            if (!await DriverHelper.ClickById(acc, "btn_ok"))
            {
                return(TaskRes.Retry);
            }

            newVillage.SettlersSent = true;
            this.Vill.Expansion.ExpansionAvailable = false;

            return(TaskRes.Executed);
        }
예제 #7
0
        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, 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 div = troopNode.Descendants("div");

            Vill.Troops.Settlers = (int)Parser.RemoveNonNumeric(div.FirstOrDefault(x => x.HasClass("tit")).Descendants("span").FirstOrDefault().InnerText);

            string innertext = "";

            switch (acc.AccInfo.ServerVersion)
            {
            case Classificator.ServerVersionEnum.T4_4:
                innertext = troopNode.ChildNodes.First(x => x.Name == "a").InnerText;
                break;

            case Classificator.ServerVersionEnum.T4_5:
                // no expansion slot
                if (div.FirstOrDefault(x => x.HasClass("noExpansionSlot")) != null)
                {
                    if (Vill.Troops.Settlers >= 3)
                    {
                        if (acc.NewVillages.AutoSettleNewVillages)
                        {
                            TaskExecutor.AddTaskIfNotExists(acc, new SendSettlers()
                            {
                                ExecuteAt = DateTime.Now.AddHours(-3),
                                Vill      = this.Vill,
                                // For high speed servers, you want to train settlers asap
                                Priority = 1000 < acc.AccInfo.ServerSpeed ? TaskPriority.High : TaskPriority.Medium,
                            });
                        }

                        acc.Wb.Log("Have enoung settlers");
                    }
                    else
                    {
                        acc.Wb.Log("Don't have enough expansion slot or settlers are training.");
                    }
                    return(TaskRes.Executed);
                }

                innertext = div.FirstOrDefault(x => x.HasClass("cta")).Descendants("a").FirstOrDefault().InnerText;
                break;
            }
            var maxNum = Parser.RemoveNonNumeric(innertext);

            Vill.Troops.Settlers = (int)TroopsParser.ParseAvailable(troopNode);

            var costNode = troopNode.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)maxNum;

            if (Vill.Troops.Settlers < 3)
            {
                // random train next settlers after 30 - 60 mins
                var ran = new Random();
                this.NextExecute = DateTime.Now.AddMinutes(ran.Next(30, 60));
            }
            else
            {
                if (acc.NewVillages.AutoSettleNewVillages)
                {
                    SendSettlersTask(acc);
                }
            }
            return(TaskRes.Executed);
        }
예제 #8
0
        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);
        }
예제 #9
0
        public override async Task <TaskRes> Execute(Account acc)
        {
            await base.Execute(acc); // Navigate to dorf2

            if (Vill == null)
            {
                Vill = acc.Villages.First(x => x.Active);
            }

            if (!await VillageHelper.EnterBuilding(acc, Vill, Classificator.BuildingEnum.Smithy))
            {
                return(TaskRes.Executed);
            }

            var levels = TroopsParser.GetTroopLevels(acc.Wb.Html);

            if (levels == null)
            {
                acc.Wb.Log("There was an error at getting Smithy troop levels");
                return(TaskRes.Executed);
            }
            Vill.Troops.Levels = levels;
            TroopsHelper.UpdateResearchedTroops(Vill);

            var currentlyImproving = TroopsParser.GetImprovingTroops(acc.Wb.Html);
            var troop = TroopToImprove(Vill, currentlyImproving);

            if (troop == Classificator.TroopsEnum.None)
            {
                return(TaskRes.Executed);
            }

            //If we have plus account we can improve 2 troops at the same time
            int maxImproving = acc.AccInfo.PlusAccount ? 2 : 1;

            if (maxImproving <= currentlyImproving.Count())
            {
                this.NextExecute = DateTime.Now.Add(currentlyImproving.Last().Time);
                return(TaskRes.Executed);
            }
            //call NextImprove() after enough res OR when this improvement finishes.

            var cost = Vill.Troops.Levels.FirstOrDefault(x => x.Troop == troop);

            // Check if we have enough resources to improve the troop
            if (!ResourcesHelper.IsEnoughRes(Vill, cost.UpgradeCost.ToArray()))
            {
                ResourcesHelper.NotEnoughRes(acc, Vill, cost.UpgradeCost, this);
                return(TaskRes.Executed);
            }

            //Click on the button
            var troopNode = acc.Wb.Html.DocumentNode.Descendants("img").FirstOrDefault(x => x.HasClass("u" + (int)troop));

            while (!troopNode.HasClass("research"))
            {
                troopNode = troopNode.ParentNode;
            }

            var button = troopNode.Descendants("button").FirstOrDefault(x => x.HasClass("green"));

            if (button == null)
            {
                acc.Wb.Log($"Could not find Upgrade button to improve {troop}");
                this.NextExecute = DateTime.Now.AddMinutes(1);
                return(TaskRes.Retry);
            }


            acc.Wb.Driver.ExecuteScript($"document.getElementById('{button.Id}').click()");
            // If we have plus account and there is currently no other troop to improve, go ahead and improve the unit again
            this.NextExecute = (currentlyImproving.Count() == 0 && maxImproving == 2) ?
                               DateTime.MinValue :
                               DateTime.Now.Add(cost.TimeCost).AddMilliseconds(5 * AccountHelper.Delay());
            return(TaskRes.Executed);
        }