/// <summary> /// Convert rares into legendaries with Kanai's cube /// </summary> /// <param name="types">restrict the rares that can be selected by ItemType</param> public static async Task <bool> Execute(List <ItemSelectionType> types = null) { while (CanRun(types)) { if (!ZetaDia.IsInTown) { break; } Logger.Log("[CubeRaresToLegendary] CubeRaresToLegendary Started! Wooo!"); var backpackGuids = new HashSet <int>(ZetaDia.Me.Inventory.Backpack.Select(i => i.ACDGuid)); if (BackpackHasMaterials) { if (Town.Locations.KanaisCube.Distance(ZetaDia.Me.Position) > 10f || !GameUI.KanaisCubeWindow.IsVisible) { if (!await MoveToAndInteract.Execute(Town.Locations.KanaisCube, Town.ActorIds.KanaisCube, 3f)) { Logger.Log("Failed to move to the cube, quite unfortunate."); break; } continue; } Logger.Log("[CubeRaresToLegendary] Ready to go, Lets transmute!"); var item = GetBackPackRares(types).First(); var itemName = item.Name; var itemDynamicId = item.DynamicId; var itemInternalName = item.InternalName; var transmuteGroup = new List <ACDItem> { item, }; transmuteGroup.AddRange(Inventory.GetStacksUpToQuantity(Inventory.Backpack.ArcaneDust, 50)); transmuteGroup.AddRange(Inventory.GetStacksUpToQuantity(Inventory.Backpack.VeiledCrystals, 50)); transmuteGroup.AddRange(Inventory.GetStacksUpToQuantity(Inventory.Backpack.ReusableParts, 50)); transmuteGroup.AddRange(Inventory.GetStacksUpToQuantity(Inventory.Backpack.DeathsBreath, 25)); await Transmute.Execute(transmuteGroup); await Coroutine.Sleep(1500); var newItem = ZetaDia.Me.Inventory.Backpack.FirstOrDefault(i => !backpackGuids.Contains(i.ACDGuid)); if (newItem != null) { var newLegendaryItem = Legendary.GetItemByACD(newItem); Logger.Log("[CubeRaresToLegendary] Upgraded Rare '{0}' ---> '{1}' ({2})", itemName, newLegendaryItem.Name, newItem.ActorSNO); } else { Logger.Log("[CubeRaresToLegendary] Failed to upgrade Item '{0}' {1} DynId={2} HasBackpackMaterials={3}", itemName, itemInternalName, itemDynamicId, BackpackHasMaterials); } Inventory.InvalidItemDynamicIds.Add(itemDynamicId); } else if (StashHasMaterials) { Logger.Log("[CubeRaresToLegendary] Getting Materials from Stash"); if (!await TakeItemsFromStash.Execute(Inventory.RareUpgradeIds, 5000)) { return(true); } } else { Logger.Log("[CubeRaresToLegendary] Oh no! Out of materials!"); return(true); } await Coroutine.Sleep(500); await Coroutine.Yield(); } return(true); }
/// <summary> /// Converts crafting materials into other types of crafting materials /// </summary> /// <param name="from">the type of material you will consume</param> /// <param name="to">the type of material you will get more of</param> public static async Task <bool> Execute(InventoryItemType from, InventoryItemType to) { Logger.Log("[ConvertMaterials] Wooo! Lets convert some {0} to {1}", from, to); if (!ZetaDia.IsInGame || !ZetaDia.IsInTown) { return(true); } if (!Inventory.MaterialConversionTypes.Contains(to) || !Inventory.MaterialConversionTypes.Contains(from)) { Logger.Log("[Cube] Unable to convert from {0} to {1}", from, to); return(true); } var backpackDeathsBreathAmount = Inventory.Backpack.DeathsBreath.Select(i => i.ItemStackQuantity).Sum(); var backpackFromMaterialAmount = Inventory.Backpack.OfType(from).Select(i => i.ItemStackQuantity).Sum(); var backpackToMaterialAmount = Inventory.Backpack.OfType(to).Select(i => i.ItemStackQuantity).Sum(); Inventory.Materials.Update(); var sacraficialItems = GetSacraficialItems(to); Logger.LogVerbose("[ConvertMaterials] Starting Material Counts DeathsBreath={0} {1}={2} {3}={4} SacraficialItems={5}", backpackDeathsBreathAmount, from, backpackFromMaterialAmount, to, backpackToMaterialAmount, sacraficialItems.Count); while (CanRun(from, to)) { Inventory.Materials.Update(); sacraficialItems = GetSacraficialItems(to); var item = sacraficialItems.First(); var transmuteGroup = new List <ACDItem> { Inventory.Backpack.DeathsBreath.First(), item }; sacraficialItems.Remove(item); // Make sure we include enough materials by adding multiple stacks if nessesary. var materialStacks = Inventory.GetStacksUpToQuantity(Inventory.Backpack.OfType(from), 50).ToList(); if (materialStacks.Any(m => !m.IsValid || m.IsDisposed) || !item.IsValid || item.IsDisposed) { Logger.LogError("[ConvertMaterials] something is terribly wrong our items are not valid"); return(true); } transmuteGroup.AddRange(materialStacks); await Transmute.Execute(transmuteGroup); await Coroutine.Sleep(1500); await Coroutine.Yield(); var newToAmount = Inventory.Backpack.OfType(to).Select(i => i.ItemStackQuantity).Sum(); if (newToAmount > backpackToMaterialAmount) { Logger.Log("[ConvertMaterials] Converted materials '{0}' ---> '{1}'", from, to); backpackToMaterialAmount = newToAmount; backpackFromMaterialAmount = Inventory.Backpack.OfType(from).Select(i => i.ItemStackQuantity).Sum(); backpackDeathsBreathAmount = Inventory.Backpack.DeathsBreath.Select(i => i.ItemStackQuantity).Sum(); ConsecutiveFailures = 0; } else { ConsecutiveFailures++; if (ConsecutiveFailures > 3) { Inventory.InvalidItemDynamicIds.Add(item.ACDGuid); } Logger.LogError("[ConvertMaterials] Failed to convert materials"); return(true); } await Coroutine.Sleep(100); await Coroutine.Yield(); } Logger.LogVerbose("[ConvertMaterials] Finishing Material Counts DeathsBreath={0} {1}={2} {3}={4} SacraficialItems={5}", backpackDeathsBreathAmount, from, backpackFromMaterialAmount, to, backpackToMaterialAmount, sacraficialItems.Count); return(true); }