public static long[] SendResCapToStorage(Account acc, Resources resources) { var mainVill = AccountHelper.GetMainVillage(acc); var stored = mainVill.Res.Stored.Resources.ToArray(); var resSend = resources.ToArray(); long[] ret = new long[4]; for (int i = 0; i < 4; i++) { ret[i] = stored[i] < resSend[i] ? stored[i] : resSend[i]; } return(ret); }
private static TimeSpan CalculateTransitTime(Account acc, Village vill1, Village vill2) { var mainVill = AccountHelper.GetMainVillage(acc); if (mainVill == null) { acc.Villages.First(); } var distance = MapHelper.CalculateDistance(acc, vill1.Coordinates, vill2.Coordinates); //Speed is per hour var speed = GetMerchantsSpeed(acc.AccInfo.Tribe ?? Classificator.TribeEnum.Any); speed *= acc.AccInfo.ServerSpeed; var hours = distance / speed; return(TimeSpan.FromHours(hours)); }
/// <summary> /// Will send resources from main village to the target village /// </summary> /// <param name="vill">(target) Village to get the resources</param> /// <returns>Returns DateTime when approximately will resources get transited to target village </returns> public static DateTime TransitResourcesFromMain(Account acc, Village vill) { // Transit resources for this village is disabled. if (!vill.Market.Settings.Configuration.Enabled) { return(DateTime.MaxValue); } // There already is a sendResources BotTask for this village var transitTask = (SendResources)acc.Tasks.FirstOrDefault(x => x.GetType() == typeof(SendResources) && ((SendResources)x).Coordinates == vill.Coordinates ); //vill.Market.Settings.Configuration. if (transitTask != null) { return(transitTask.Configuration.TransitArrival); } //Less than 5min ago we already sent resources. Just to catch bugs. //if(vill.Market.) // Merchants are on their way if (vill.Market.Settings.Configuration.TransitArrival > DateTime.Now) { return(vill.Market.Settings.Configuration.TransitArrival); } //send resources var sendRes = new Resources(); var conf = vill.Market.Settings.Configuration; var currentRes = vill.Res.Stored.Resources; var cap = vill.Res.Capacity; var woodNeeded = (long)(cap.WarehouseCapacity * conf.TargetLimit.Wood / 100.0); sendRes.Wood = (woodNeeded > conf.FillLimit.Wood ? conf.FillLimit.Wood : woodNeeded) - currentRes.Wood; sendRes.Wood = (sendRes.Wood < 0 ? 0 : sendRes.Wood); var clayNeeded = (long)(cap.WarehouseCapacity * conf.TargetLimit.Clay / 100.0); sendRes.Clay = (clayNeeded > conf.FillLimit.Clay ? conf.FillLimit.Clay : clayNeeded) - currentRes.Clay; sendRes.Clay = (sendRes.Clay < 0 ? 0 : sendRes.Clay); var ironNeeded = (long)(cap.WarehouseCapacity * conf.TargetLimit.Iron / 100.0); sendRes.Iron = (ironNeeded > conf.FillLimit.Iron ? conf.FillLimit.Iron : ironNeeded) - currentRes.Iron; sendRes.Iron = (sendRes.Iron < 0 ? 0 : sendRes.Iron); var cropNeeded = (long)(cap.GranaryCapacity * conf.TargetLimit.Crop / 100.0); sendRes.Crop = (cropNeeded > conf.FillLimit.Crop ? conf.FillLimit.Crop : cropNeeded) - currentRes.Crop; sendRes.Crop = (sendRes.Crop < 0 ? 0 : sendRes.Crop); if (ResourcesHelper.IsZeroResources(sendRes)) //we have enough res :) { return(DateTime.MinValue); } // Send resources to a village only once per 5 minutes TimeSpan transitAfter = vill.Market.LastTransit.AddMinutes(5) - DateTime.Now; if (transitAfter < TimeSpan.Zero) { transitAfter = TimeSpan.Zero; } var sendResTask = new SendResources { Configuration = conf, Coordinates = vill.Coordinates, ExecuteAt = DateTime.Now + transitAfter, Vill = AccountHelper.GetMainVillage(acc), Resources = sendRes }; TaskExecutor.AddTask(acc, sendResTask); //AddMinutes(1) since bot has to wait for the SendResources task and then //go to the marketplace and send resources //TransitArrival will get updated to more specific time return(DateTime.Now.Add(transitAfter + CalculateTransitTimeMainVillage(acc, vill)).AddMinutes(1)); }
/// <summary> /// Calculates the time it takes for resources to be transited from main village (supplying village) to target village /// </summary> /// <param name="acc">Account</param> /// <param name="targetVillage">Target village to receive the resources</param> /// <returns></returns> private static TimeSpan CalculateTransitTimeMainVillage(Account acc, Village targetVillage) { return(CalculateTransitTime(acc, targetVillage, AccountHelper.GetMainVillage(acc))); }
/// <summary> /// If there are enough resources, return TimeSpan(0) /// Otherwise calculate how long it will take to get enough resources and transit res from /// main village, if we have that enabled. Return the one that takes less time. /// DateTime for usage in nextExecution time /// </summary> /// <param name="acc">Account</param> /// <param name="vill">(target) Village</param> /// <param name="requiredRes">Resources required</param> /// <param name="task">Bot task that doesn't have enough resources</param> /// <param name="buildingTask">Potential building task</param> /// <returns>When next village update should occur</returns> private static DateTime?NewUnfinishedTask(Account acc, Village vill, Resources requiredRes, BotTask task, BuildingTask buildingTask = null) { var stillNeededRes = SubtractResources(requiredRes.ToArray(), vill.Res.Stored.Resources.ToArray(), true); // Whether we have enough resources. This should already be checked before calling this method! if (IsZeroResources(stillNeededRes)) { ResSpendingHelper.AddUnfinishedTask(vill, task, requiredRes); return(DateTime.Now); } acc.Wb.Log($"Not enough resources for the task {task.GetName()}! Needed {requiredRes}. Bot will try finish the task later"); if (IsStorageTooLow(acc, vill, requiredRes)) { acc.Wb.Log($"Storage is too low."); ResSpendingHelper.AddUnfinishedTask(vill, task, requiredRes); return(null); } // Try to use hero resources first if (vill.Settings.UseHeroRes && acc.AccInfo.ServerVersion == ServerVersionEnum.T4_5) // Only T4.5 has resources in hero inv { var heroRes = HeroHelper.GetHeroResources(acc); // If we have some hero resources, we should use those first if (!IsZeroResources(heroRes)) { var heroEquipTask = UseHeroResources(acc, vill, ref stillNeededRes, heroRes, buildingTask); // If we have enough hero res for our task, execute the task // right after hero equip finishes if (IsZeroResources(SubtractResources(stillNeededRes, heroRes, true))) { heroEquipTask.NextTask = task; return(null); } } } ResSpendingHelper.AddUnfinishedTask(vill, task, requiredRes); // When will we have enough resources from production DateTime enoughRes = TimeHelper.EnoughResToUpgrade(vill, stillNeededRes); var mainVill = AccountHelper.GetMainVillage(acc); if (mainVill == vill) { return(enoughRes); } DateTime resTransit = MarketHelper.TransitResourcesFromMain(acc, vill); if (resTransit < enoughRes) { enoughRes = resTransit; } if (enoughRes < DateTime.Now) { return(DateTime.Now); } return(enoughRes); }