public static TownNpc GetCurrencyVendor() { var area = World.CurrentArea; if (area.IsHideoutArea) { GlobalLog.Error("[GetCurrencyVendor] Cannot buy currency in hideout."); return(null); } if (area.IsTown) { switch (area.Act) { case 11: return(Lani_A11); case 10: return(Lani_A10); case 9: return(PetarusAndVanja_A9); case 8: return(Clarissa_A8); case 7: return(Yeena_A7); case 6: return(Bestel_A6); case 5: return(Lani); case 4: return(PetarusAndVanja); case 3: return(Clarissa); case 2: return(Yeena); case 1: return(Nessa); } } GlobalLog.Error($"[GetCurrencyVendor] Unsupported area for currency vendor \"{area.Name}\"."); return(null); }
public static async Task <bool> For(Func <bool> condition, string desc, Func <int> step, int timeout = 3000) { if (condition()) { return(true); } var timer = Stopwatch.StartNew(); while (timer.ElapsedMilliseconds < timeout) { await StuckDetectionSleep(step()); GlobalLog.Debug($"[WaitFor] Waiting for {desc} ({Math.Round(timer.ElapsedMilliseconds / 1000f, 2)}/{timeout / 1000f})"); if (condition()) { return(true); } } GlobalLog.Error($"[WaitFor] Wait for {desc} timeout."); return(false); }
public static async Task <bool> OpenStash() { if (StashUi.IsOpened) { return(true); } WalkablePosition stashPos; if (World.CurrentArea.IsTown) { stashPos = StaticPositions.GetStashPosByAct(); } else { var stashObj = LokiPoe.ObjectManager.Stash; if (stashObj == null) { GlobalLog.Error("[OpenStash] Fail to find any Stash nearby."); return(false); } stashPos = stashObj.WalkablePosition(); } await PlayerAction.EnableAlwaysHighlight(); await stashPos.ComeAtOnce(); if (!await PlayerAction.Interact(LokiPoe.ObjectManager.Stash, () => StashUi.IsOpened && StashUi.StashTabInfo != null, "stash opening")) { return(false); } await Wait.SleepSafe(200); return(true); }
private static async Task <bool> GoToHideoutViaWaypoint() { if (!LokiPoe.InGameState.WorldUi.IsOpened) { if (!await OpenWaypoint()) { GlobalLog.Error("[GoToHideoutViaWaypoint] Fail to open a waypoint."); return(false); } } GlobalLog.Debug("[GoToHideoutViaWaypoint] Now going to take a waypoint to hideout."); var areaHash = LokiPoe.LocalData.AreaHash; var err = LokiPoe.InGameState.WorldUi.GoToHideout(); if (err != LokiPoe.InGameState.TakeWaypointResult.None) { GlobalLog.Error($"[GoToHideoutViaWaypoint] Fail to take a waypoint to hideout. Error: \"{err}\"."); return(false); } return(await Wait.ForAreaChange(areaHash)); }
public static async Task <bool> TakeWaypoint(AreaInfo area, bool newInstance = false) { if (!LokiPoe.InGameState.WorldUi.IsOpened) { if (!await OpenWaypoint()) { GlobalLog.Error("[TakeWaypoint] Fail to open a waypoint."); return(false); } } GlobalLog.Debug($"[TakeWaypoint] Now going to take a waypoint to {area}"); var areaHash = LokiPoe.LocalData.AreaHash; var err = LokiPoe.InGameState.WorldUi.TakeWaypoint(area.Id, newInstance); if (err != LokiPoe.InGameState.TakeWaypointResult.None) { GlobalLog.Error($"[TakeWaypoint] Fail to take a waypoint to {area}. Error: \"{err}\"."); return(false); } return(await Wait.ForAreaChange(areaHash)); }
public static WorldPosition FindWaypoint() { var positions = new List <WorldPosition>(); var tgtEntries = LokiPoe.TerrainData.TgtEntries; for (int i = 0; i < tgtEntries.GetLength(0); i++) { for (int j = 0; j < tgtEntries.GetLength(1); j++) { var entry = tgtEntries[i, j]; if (entry == null) { continue; } var name = entry.TgtName; if (name.ContainsIgnorecase("waypoint") && !name.Contains("waypoint_broken")) { positions.Add(new WorldPosition(i * 23, j * 23)); } } } if (positions.Count == 0) { GlobalLog.Error("[FindWaypoint] Fail to find any waypoint tgt."); return(null); } foreach (var pos in positions) { if (pos.PathExists) { return(pos); } } return(positions[0].GetWalkable(10, 20)); }
public static async Task <bool> FastMoveFromInventory(Vector2i itemPos) { var item = InventoryUi.InventoryControl_Main.Inventory.FindItemByPos(itemPos); if (item == null) { GlobalLog.Error($"[FastMoveFromInventory] Fail to find item at {itemPos} in player's inventory."); return(false); } var itemName = item.FullName; GlobalLog.Debug($"[FastMoveFromInventory] Fast moving \"{itemName}\" at {itemPos} from player's inventory."); var err = InventoryUi.InventoryControl_Main.FastMove(item.LocalId); if (err != FastMoveResult.None) { GlobalLog.Error($"[FastMoveFromInventory] Fast move error: \"{err}\"."); return(false); } if (await Wait.For(() => InventoryUi.InventoryControl_Main.Inventory.FindItemByPos(itemPos) == null, "fast move")) { GlobalLog.Debug($"[FastMoveFromInventory] \"{itemName}\" at {itemPos} has been successfully fast moved from player's inventory."); if (Settings.Instance.ArtificialDelays) { await Wait.ArtificialDelay(); } return(true); } GlobalLog.Error($"[FastMoveFromInventory] Fast move timeout for \"{itemName}\" at {itemPos} in player's inventory."); return(false); }
public static void ReportCriticalError() { GlobalLog.Error("[CRITICAL ERROR] Now requesting bot to stop."); BotManager.Stop(); throw new Exception("CRITICAL_ERROR"); }
public static void ReportError(string error) { SpecificErrors.TryGetValue(error, out var count); SpecificErrors[error] = ++count; GlobalLog.Error($"[ErrorManager] \"{error}\" error count: {count}"); }
public static async Task <bool> SellItems(List <Vector2i> itemPositions) { if (itemPositions == null) { GlobalLog.Error("[SellItems] Item list for sell is null."); return(false); } if (itemPositions.Count == 0) { GlobalLog.Error("[SellItems] Item list for sell is empty."); return(false); } var vendor = GetSellVendor(); if (vendor == null) { return(false); } if (!await vendor.OpenSellPanel()) { return(false); } itemPositions.Sort(Position.Comparer.Instance); var soldItems = new List <CachedItem>(itemPositions.Count); foreach (var itemPos in itemPositions) { var item = InventoryUi.InventoryControl_Main.Inventory.FindItemByPos(itemPos); if (item == null) { GlobalLog.Error($"[SellItems] Fail to find item at {itemPos}. Skipping it."); continue; } soldItems.Add(new CachedItem(item)); if (!SellUi.TradeControl.InventoryControl_YourOffer.Inventory.CanFitItem(item.Size)) { break; } if (!await Inventories.FastMoveToVendor(itemPos)) { return(false); } } var gainedItems = new List <CachedItem>(); foreach (var item in SellUi.TradeControl.InventoryControl_OtherOffer.Inventory.Items) { gainedItems.Add(new CachedItem(item)); } var accepted = SellUi.TradeControl.Accept(); if (accepted != TradeResult.None) { GlobalLog.Error($"[SellItems] Fail to accept sell. Error: \"{accepted}\"."); return(false); } if (!await Wait.For(() => !SellUi.IsOpened, "sell panel closing")) { await Coroutines.CloseBlockingWindows(); return(false); } // game needs some time do despawn sold items from inventory await Wait.SleepSafe(200); GlobalLog.Info($"[Events] Items sold ({soldItems.Count})"); Utility.BroadcastMessage(null, Events.Messages.ItemsSoldEvent, soldItems, gainedItems); return(true); }
public static async Task <Portal> CreateTownPortal() { var portalSkill = LokiPoe.InGameState.SkillBarHud.Skills.FirstOrDefault(s => s.Name == "Portal" && s.IsOnSkillBar); if (portalSkill != null) { await Coroutines.FinishCurrentAction(); await Wait.SleepSafe(100); var err = LokiPoe.InGameState.SkillBarHud.Use(portalSkill.Slot, false); if (err != LokiPoe.InGameState.UseResult.None) { GlobalLog.Error($"[CreateTownPortal] Fail to cast portal skill. Error: \"{err}\"."); return(null); } await Coroutines.FinishCurrentAction(); await Wait.SleepSafe(100); } else { var portalScroll = Inventories.InventoryItems .Where(i => i.Name == CurrencyNames.Portal) .OrderBy(i => i.StackCount) .FirstOrDefault(); if (portalScroll == null) { GlobalLog.Error("[CreateTownPortal] Out of portal scrolls."); return(null); } int itemId = portalScroll.LocalId; if (!await Inventories.OpenInventory()) { return(null); } await Coroutines.FinishCurrentAction(); await Wait.SleepSafe(100); var err = LokiPoe.InGameState.InventoryUi.InventoryControl_Main.UseItem(itemId); if (err != UseItemResult.None) { GlobalLog.Error($"[CreateTownPortal] Fail to use a Portal Scroll. Error: \"{err}\"."); return(null); } if (Settings.Instance.ArtificialDelays) { await Wait.ArtificialDelay(); } await Coroutines.CloseBlockingWindows(); } Portal portal = null; await Wait.For(() => (portal = PortalInRangeOf(40)) != null, "portal spawning"); return(portal); }
public static async Task <bool> PlaceItemFromCursor(this InventoryControlWrapper inventory, Vector2i pos) { var cursorItem = Cursor.Item; if (cursorItem == null) { GlobalLog.Error("[PlaceItemFromCursor] Cursor item is null."); return(false); } GlobalLog.Debug($"[PlaceItemFromCursor] Now going to place \"{cursorItem.Name}\" from cursor to {pos}."); //apply item on another item, if we are in VirtualUse mode if (Cursor.Mode == LokiPoe.InGameState.CursorItemModes.VirtualUse) { var destItem = inventory.Inventory.FindItemByPos(pos); if (destItem == null) { GlobalLog.Error("[PlaceItemFromCursor] Destination item is null."); return(false); } int destItemId = destItem.LocalId; var applied = inventory.ApplyCursorTo(destItem.LocalId); if (applied != ApplyCursorResult.None) { GlobalLog.Error($"[PlaceItemFromCursor] Fail to place item from cursor. Error: \"{applied}\"."); return(false); } //wait for destination item change, it cannot become null, ID should change return(await Wait.For(() => { var item = inventory.Inventory.FindItemByPos(pos); return item != null && item.LocalId != destItemId; }, "destination item change")); } //in other cases, place item to empty inventory slot or swap it with another item int cursorItemId = cursorItem.LocalId; var placed = inventory.PlaceCursorInto(pos.X, pos.Y, true); if (placed != PlaceCursorIntoResult.None) { GlobalLog.Error($"[PlaceItemFromCursor] Fail to place item from cursor. Error: \"{placed}\"."); return(false); } //wait for cursor item change, if we placed - it should become null, if we swapped - ID should change if (!await Wait.For(() => { var item = Cursor.Item; return(item == null || item.LocalId != cursorItemId); }, "cursor item change")) { return(false); } if (Settings.Instance.ArtificialDelays) { await Wait.ArtificialDelay(); } return(true); }
public static async Task <WithdrawResult> WithdrawCurrency(string name) { foreach (var tab in Settings.Instance.GetTabsForCurrency(name)) { GlobalLog.Debug($"[WithdrawCurrency] Looking for \"{name}\" in \"{tab}\" tab."); if (!await OpenStashTab(tab)) { return(WithdrawResult.Error); } var tabType = StashUi.StashTabInfo.TabType; if (tabType == InventoryTabType.Currency) { var control = GetControlWithCurrency(name); if (control == null) { GlobalLog.Debug($"[WithdrawCurrency] There are no \"{name}\" in \"{tab}\" tab."); continue; } if (!await FastMoveFromPremiumStashTab(control)) { return(WithdrawResult.Error); } GlobalLog.Debug($"[WithdrawCurrency] \"{name}\" have been successfully taken from \"{tab}\" tab."); return(WithdrawResult.Success); } if (tabType == InventoryTabType.Essence) { var control = StashUi.EssenceTab.NonEssences.FirstOrDefault(c => c.CustomTabItem?.Name == name); if (control == null) { GlobalLog.Debug($"[WithdrawCurrency] There are no \"{name}\" in \"{tab}\" tab."); continue; } if (!await FastMoveFromPremiumStashTab(control)) { return(WithdrawResult.Error); } GlobalLog.Debug($"[WithdrawCurrency] \"{name}\" have been successfully taken from \"{tab}\" tab."); return(WithdrawResult.Success); } if (tabType == InventoryTabType.Divination || tabType == InventoryTabType.Map || tabType == InventoryTabType.Fragment) { GlobalLog.Error($"[WithdrawCurrency] Unsupported behavior. Current stash tab is {tabType}."); continue; } var item = StashTabItems.Where(i => i.Name == name).OrderByDescending(i => i.StackCount).FirstOrDefault(); if (item == null) { GlobalLog.Debug($"[WithdrawCurrency] There are no \"{name}\" in \"{tab}\" tab."); continue; } if (!await FastMoveFromStashTab(item.LocationTopLeft)) { return(WithdrawResult.Error); } GlobalLog.Debug($"[WithdrawCurrency] \"{name}\" have been successfully taken from \"{tab}\" tab."); return(WithdrawResult.Success); } return(WithdrawResult.Unavailable); }