private static async Task <bool> ClearDevice() { var itemPositions = MapDevice.InventoryControl.Inventory.Items.Select(i => i.LocationTopLeft).ToList(); if (itemPositions.Count == 0) { return(true); } GlobalLog.Error("[OpenMapTask] Map Device is not empty. Now going to clean it."); foreach (var itemPos in itemPositions) { if (!await PlayerAction.TryTo(() => FastMoveFromDevice(itemPos), null, 2)) { return(false); } } GlobalLog.Debug("[OpenMapTask] Map Device has been successfully cleaned."); return(true); }
public static async Task <bool> RerollMagic(Vector2i mapPos) { while (true) { var map = InventoryUi.InventoryControl_Main.Inventory.FindItemByPos(mapPos); if (map == null) { GlobalLog.Error($"[RerollMagic] Fail to find a map at {mapPos}."); return(false); } var rarity = map.RarityLite(); if (rarity != Rarity.Magic) { GlobalLog.Error($"[TakeMapTask] RerollMagic is called on {rarity} map."); return(false); } var affix = map.GetBannedAffix(); if (affix != null) { GlobalLog.Info($"[RerollMagic] Rerolling banned \"{affix}\" affix."); if (!await ApplyOrb(mapPos, CurrencyNames.Alteration)) { return(false); } continue; } if (map.CanAugment() && HasCurrency(CurrencyNames.Augmentation)) { if (!await ApplyOrb(mapPos, CurrencyNames.Augmentation)) { return(false); } continue; } return(true); } }
public static bool PremiumTabCanFit(string metadata) { var tabType = StashUi.StashTabInfo.TabType; if (tabType == InventoryTabType.Currency) { var control = StashUi.CurrencyTab.GetInventoryControlForMetadata(metadata); if (control != null && ControlCanFit(control, metadata)) { return(true); } return(StashUi.CurrencyTab.NonCurrency.Any(miscControl => ControlCanFit(miscControl, metadata))); } if (tabType == InventoryTabType.Essence) { var control = StashUi.EssenceTab.GetInventoryControlForMetadata(metadata); if (control != null && ControlCanFit(control, metadata)) { return(true); } return(StashUi.EssenceTab.NonEssences.Any(miscControl => ControlCanFit(miscControl, metadata))); } if (tabType == InventoryTabType.Divination) { var control = StashUi.DivinationTab.GetInventoryControlForMetadata(metadata); return(control != null && ControlCanFit(control, metadata)); } if (tabType == InventoryTabType.Fragment) { var control = StashUi.FragmentTab.GetInventoryControlForMetadata(metadata); return(control != null && ControlCanFit(control, metadata)); } GlobalLog.Error("[StashTask] PremiumTabCanFit was called for unknown premium tab type."); return(false); }
public static async Task <bool> ApplyChisels(Vector2i mapPos) { while (true) { var map = InventoryUi.InventoryControl_Main.Inventory.FindItemByPos(mapPos); if (map == null) { GlobalLog.Error($"[ApplyChisels] Fail to find a map at {mapPos}."); return(false); } if (map.Quality >= 18) { return(true); } if (!await ApplyOrb(mapPos, CurrencyNames.Chisel)) { return(false); } } }
private static Position GetMovePosForInventoryItem(Item item) { var itemName = item.Name; var currency = Settings.Instance.InventoryCurrencies.FirstOrDefault(i => i.Name == itemName); if (currency != null && HasFixedPosition(currency)) { var destination = new Position(currency.Column - 1, currency.Row - 1); if (destination != item.LocationTopLeft) { if (OccupiedBySameItem(itemName, destination)) { GlobalLog.Error($"[SortInventoryTask] Unexpected error. \"{itemName}\" will not be sorted correctly because destination position is already occupied by the same item."); return(GetMovePosLessThanCurrent(item)); } return(destination); } return(null); } return(GetMovePosLessThanCurrent(item)); }
public async Task <bool> Run() { if (_triggerMetadata == null || MapExplorationTask.MapCompleted) { return(false); } if (_trigger == null || _trigger.Ignored || _trigger.Unwalkable) { return(false); } if (!World.CurrentArea.IsMap) { return(false); } var pos = _trigger.Position; if (pos.Distance > 10 || pos.PathDistance > 12) { if (!pos.TryCome()) { GlobalLog.Error($"[ProximityTriggerTask] Fail to move to {pos}. Marking this trigger object as unwalkable."); _trigger.Unwalkable = true; } return(true); } await Coroutines.FinishCurrentAction(); if (_waitFunc != null) { await _waitFunc(); } _triggerMetadata = null; return(true); }
private void Load() { if (!File.Exists(SettingsPath)) { return; } var json = File.ReadAllText(SettingsPath); if (string.IsNullOrWhiteSpace(json)) { GlobalLog.Error("[MapBot] Fail to load \"MapSettings.json\". File is empty."); return; } var parts = JsonConvert.DeserializeObject <Dictionary <string, EditablePart> >(json); if (parts == null) { GlobalLog.Error("[MapBot] Fail to load \"MapSettings.json\". Json deserealizer returned null."); return; } foreach (var data in MapList) { if (parts.TryGetValue(data.Name, out var part)) { data.Priority = part.Priority; data.Ignored = part.Ignore; data.IgnoredBossroom = part.IgnoreBossroom; data.Sextant = part.Sextant; data.ZanaMod = part.ZanaMod; data.MobRemaining = part.MobRemaining; data.StrictMobRemaining = part.StrictMobRemaining; data.ExplorationPercent = part.ExplorationPercent; data.StrictExplorationPercent = part.StrictExplorationPercent; data.TrackMob = part.TrackMob; data.FastTransition = part.FastTransition; } } }
private static async Task <bool> HandleNormalMap(Vector2i mapPos) { var map = InventoryUi.InventoryControl_Main.Inventory.FindItemByPos(mapPos); if (map == null) { GlobalLog.Error($"[HandleNormalMap] Fail to find a map at {mapPos}."); return(false); } if (map.ShouldUpgrade(Settings.ChiselUpgrade) && HasCurrency(CurrencyNames.Chisel)) { if (!await ApplyChisels(mapPos)) { return(false); } UpdateMapReference(mapPos, ref map); } if (map.ShouldUpgrade(Settings.RareUpgrade) && HasRareOrbs) { if (!await ApplyOrb(mapPos, CurrencyNames.Alchemy)) { return(false); } return(await RerollRare(mapPos)); } if (map.ShouldUpgrade(Settings.MagicUpgrade) && HasMagicOrbs) { if (!await ApplyOrb(mapPos, CurrencyNames.Transmutation)) { return(false); } return(await RerollMagic(mapPos)); } return(true); }
public async Task <bool> Run() { if (!World.CurrentArea.IsCombatArea) { return(false); } var mapIconOwner = Abyss.CachedData.MapIconOwner; if (mapIconOwner == null || mapIconOwner.Unwalkable || mapIconOwner.Ignored) { return(false); } var pos = mapIconOwner.Position; if (pos.Distance > 10 || pos.PathDistance > 10) { if (!pos.TryCome()) { GlobalLog.Error($"[FollowAbyssTask] Fail to move to {pos}. Current abyss map icon owner is unwalkable."); mapIconOwner.Unwalkable = true; } return(true); } var attempts = ++mapIconOwner.InteractionAttempts; if (attempts > MaxAttempts) { GlobalLog.Error("[FollowAbyssTask] Abyss map icon owner change timeout. Now ignoring it."); mapIconOwner.Ignored = true; return(true); } GlobalLog.Debug($"[FollowAbyssTask] Waiting for abyss map icon owner change ({attempts}/{MaxAttempts})"); await Wait.Sleep(200); return(true); }
private static void HandleStuck() { if (StopBotOnStuck) { GlobalLog.Warn("[StuckDetection] StopBotOnStuck is true. Now reseting stuck counters and stopping the bot."); Reset(); BotManager.Stop(); return; } var cache = CombatAreaCache.Current; ++cache.StuckCount; GlobalLog.Error($"[StuckDetection] Stuck incidents in current area: {cache.StuckCount}"); if (cache.StuckCount >= Settings.Instance.MaxStucksPerInstance) { GlobalLog.Error($"[StuckDetection] Too many stuck incidents in current area ({World.CurrentArea.Name}). Now requesting a new instance."); EXtensions.AbandonCurrentArea(); } var err = LokiPoe.EscapeState.LogoutToTitleScreen(); if (err != LokiPoe.EscapeState.LogoutError.None) { GlobalLog.Error($"[StuckDetection] Logout error: \"{err}\"."); //stuck incident was not properly handled if we did not logout --cache.StuckCount; } else { GlobalLog.Info($"[StuckDetection] Triggered event ({cache.StuckCount})"); Triggered?.Invoke(cache.StuckCount); Utility.BroadcastMessage(null, TriggeredMessage); Reset(); } }
public static async Task <bool> TurnInQuest() { if (!Helpers.PlayerHasQuestItem(QuestItemMetadata.EyeOfDesire)) { return(false); } if (World.Act4.CrystalVeins.IsCurrentArea) { var dialla = Helpers.LadyDialla; if (dialla == null) { GlobalLog.Error("[KingOfDesire] Fail to detect Lady Dialla in Crystal Veins."); ErrorManager.ReportCriticalError(); return(true); } await Helpers.TalkTo(dialla); return(true); } await Travel.To(World.Act4.CrystalVeins); return(true); }
public static async Task <bool> ClearStrand() { if (_finished) { return(false); } if (World.Act6.TwilightStrand.IsCurrentArea) { if (await TrackMobLogic.Execute()) { return(true); } if (!await CombatAreaCache.Current.Explorer.Execute()) { if (QuestManager.GetState(Quests.FallenFromGrace) <= FinishedStateMinimum) { return(false); } GlobalLog.Error("[ClearTwilightStrand] Twilight Strand is fully explored but not all monsters were killed. Now going to create a new Twilight Strand instance."); Travel.RequestNewInstance(World.Act6.TwilightStrand); if (!await PlayerAction.TpToTown()) { ErrorManager.ReportError(); } } return(true); } await Travel.To(World.Act6.TwilightStrand); return(true); }
private static async Task <bool> OpenDevice() { if (MapDevice.IsOpen) { return(true); } var device = LokiPoe.ObjectManager.MapDevice; if (device == null) { if (World.CurrentArea.IsHideoutArea) { GlobalLog.Error("[OpenMapTask] Fail to find Map Device in hideout."); } else { GlobalLog.Error("[OpenMapTask] Unknown error. Fail to find Map Device in Templar Laboratory."); } GlobalLog.Error("[OpenMapTask] Now stopping the bot because it cannot continue."); BotManager.Stop(); return(false); } GlobalLog.Debug("[OpenMapTask] Now going to open Map Device."); await device.WalkablePosition().ComeAtOnce(); if (await PlayerAction.Interact(device, () => MapDevice.IsOpen, "Map Device opening")) { GlobalLog.Debug("[OpenMapTask] Map Device has been successfully opened."); return(true); } GlobalLog.Debug("[OpenMapTask] Fail to open Map Device."); return(false); }
private bool BasicExploration() { var explorer = BasicExplorer; if (!explorer.HasLocation) { return(false); } var location = explorer.Location; if (LogInterval.Elapsed) { var distance = LokiPoe.MyPosition.Distance(location); var percent = Math.Round(explorer.PercentComplete, 1); GlobalLog.Debug($"[ComplexExplorer] Exploring to the location {location} ({distance}) [{percent} %]."); } if (!PlayerMoverManager.MoveTowards(location)) { GlobalLog.Error($"[ComplexExplorer] MoveTowards failed for {location}. Adding this location to ignore list."); explorer.Ignore(location); } return(true); }
public static async Task <bool> Kill(NetworkObject bandit) { if (bandit == null) { GlobalLog.Error("[KillBandit] Bandit object is null."); return(false); } await bandit.WalkablePosition().ComeAtOnce(); if (!await OpenBanditPanel(bandit)) { return(false); } var err = LokiPoe.InGameState.BanditPanel.KillBandit(); if (err != LokiPoe.InGameState.TalkToBanditResult.None) { GlobalLog.Error($"[KillBandit] Fail to select \"Kill\" option. Error: \"{err}\"."); return(false); } return(true); }
public async Task <bool> Run() { if (MapBot.IsOnRun) { return(false); } var area = World.CurrentArea; if (!area.IsTown && !area.IsHideoutArea) { return(false); } if (Settings.StopRequested) { GlobalLog.Warn("Stopping the bot by a user's request (stop after current map)"); Settings.StopRequested = false; BotManager.Stop(); return(true); } var mapTabs = ExSettings.Instance.GetTabsForCategory(ExSettings.StashingCategory.Map); Item map; foreach (var tab in mapTabs) { if (!await Inventories.OpenStashTab(tab)) { ErrorManager.ReportError(); return(true); } if (StashUi.StashTabInfo.IsPremiumMap) { GlobalLog.Error("Map stash tab is unsupported and there are no plans to support it in the future. Please remove it from stashing settings."); BotManager.Stop(); return(true); } if ((map = FindProperMap()) != null) { goto hasProperMap; } GlobalLog.Debug($"[TakeMapTask] Fail to find a proper map in \"{tab}\" tab."); } GlobalLog.Error("[TakeMapTask] Fail to find a proper map in all map tabs. Now stopping the bot because it cannot continue."); BotManager.Stop(); return(true); hasProperMap: GlobalLog.Info($"[TakeMapTask] Map of choice is \"{map.Name}\" (Tier: {map.MapTier})"); if (!await Inventories.FastMoveFromStashTab(map.LocationTopLeft)) { ErrorManager.ReportError(); return(true); } if (!await Wait.For(() => (map = Inventories.InventoryItems.Find(i => i.IsMap())) != null, "map appear in inventory")) { GlobalLog.Error("[TakeMapTask] Unexpected error. Map did not appear in player's inventory after fast move from stash."); return(true); } var mapPos = map.LocationTopLeft; var mapRarity = map.RarityLite(); if (mapRarity == Rarity.Unique || !map.IsIdentified || map.IsMirrored || map.IsCorrupted) { ChooseMap(mapPos); return(false); } switch (mapRarity) { case Rarity.Normal: if (!await HandleNormalMap(mapPos)) { return(true); } break; case Rarity.Magic: if (!await HandleMagicMap(mapPos)) { return(true); } break; case Rarity.Rare: if (!await HandleRareMap(mapPos)) { return(true); } break; default: GlobalLog.Error($"[TakeMapTask] Unknown map rarity: \"{mapRarity}\"."); ErrorManager.ReportCriticalError(); return(true); } UpdateMapReference(mapPos, ref map); if (map.ShouldUpgrade(Settings.VaalUpgrade) && HasCurrency(CurrencyNames.Vaal)) { if (!await CorruptMap(mapPos)) { return(true); } UpdateMapReference(mapPos, ref map); } if (map.ShouldUpgrade(Settings.FragmentUpgrade) && _hasFragments) { await GetFragment(); } ChooseMap(mapPos); return(false); }
private static async Task GetFragment() { var tabs = new List <string>(ExSettings.Instance.GetTabsForCategory(ExSettings.StashingCategory.Fragment)); if (tabs.Count > 1 && StashUi.IsOpened) { var currentTab = StashUi.StashTabInfo.DisplayName; var index = tabs.IndexOf(currentTab); if (index > 0) { var tab = tabs[index]; tabs.RemoveAt(index); tabs.Insert(0, tab); } } foreach (var tab in tabs) { GlobalLog.Debug($"[TakeMapTask] Looking for Sacrifice Fragment in \"{tab}\" tab."); if (!await Inventories.OpenStashTab(tab)) { return; } if (StashUi.StashTabInfo.IsPremiumSpecial) { var tabType = StashUi.StashTabInfo.TabType; if (tabType == InventoryTabType.Fragment) { foreach (var control in SacrificeControls) { var fragment = control.CustomTabItem; if (fragment != null) { GlobalLog.Debug($"[TakeMapTask] Found \"{fragment.Name}\" in \"{tab}\" tab."); await Inventories.FastMoveFromPremiumStashTab(control); return; } GlobalLog.Debug($"[TakeMapTask] There are no Sacrifice Fragments in \"{tab}\" tab."); } } else { GlobalLog.Error($"[TakeMapTask] Incorrect tab type ({tabType}) for sacrifice fragments."); } } else { var fragment = Inventories.StashTabItems .Where(i => i.IsSacrificeFragment()) .OrderBy(i => i.Name == "Sacrifice at Midnight") // move midnights to the end of the list .FirstOrDefault(); if (fragment != null) { GlobalLog.Debug($"[TakeMapTask] Found \"{fragment.Name}\" in \"{tab}\" tab."); await Inventories.FastMoveFromStashTab(fragment.LocationTopLeft); return; } GlobalLog.Debug($"[TakeMapTask] There are no Sacrifice Fragments in \"{tab}\" tab."); } } GlobalLog.Info("[TakeMapTask] There are no Sacrifice Fragments in all tabs assigned to them. Now marking them as unavailable."); _hasFragments = false; }
private static async Task <bool> CurrencyPurchase(CurrencyInfo currency) { if (!await TownNpcs.GetCurrencyVendor().OpenPurchasePanel()) { return(false); } await Wait.SleepSafe(500); var name = currency.Name; var item = PurchaseUi.InventoryControl.Inventory.Items.Find(i => i.Name == name); if (item == null) { GlobalLog.Error($"[CurrencyPurchase] Unexpected error. Fail to find \"{name}\" in vendor's inventory."); return(false); } var id = item.LocalId; using (new InputDelayOverride(10)) { while (currency.Amount > 0) { if (BotManager.IsStopping) { GlobalLog.Debug("[CurrencyPurchase] Bot is stopping. Now breaking from purchase loop."); break; } if (!LokiPoe.IsInGame) { GlobalLog.Error("[CurrencyPurchase] Disconnected during currency purchase."); break; } if (!HasInvenotorySpaceForCurrency(name)) { GlobalLog.Warn("[CurrencyPurchase] Not enough inventory space."); break; } GlobalLog.Info($"Purchasing \"{name}\" ({currency.Amount})"); var moved = PurchaseUi.InventoryControl.FastMove(id); if (moved != FastMoveResult.None) { GlobalLog.Error($"[CurrencyPurchase] Fail to purchase. Error: \"{moved}\"."); return(false); } --currency.Amount; } } if (currency.Amount == 0) { CurrencyToBuy.RemoveAt(0); } return(true); }
public static async Task <bool> FullTabCheck() { if (!await Inventories.OpenStash()) { return(false); } var actualTabs = StashUi.TabControl.TabNames; var cleanedTabs = new List <Settings.FullTabInfo>(); foreach (var tab in Settings.Instance.FullTabs) { var tabName = tab.Name; if (!actualTabs.Contains(tabName)) { GlobalLog.Warn($"[FullTabCheck] \"{tabName}\" tab no longer exists. Removing it from full tab list."); cleanedTabs.Add(tab); continue; } if (!await Inventories.OpenStashTab(tabName)) { return(false); } // Can happen only if user gave map tab a name that was marked as full previously if (StashUi.StashTabInfo.IsPremiumMap) { GlobalLog.Error("[FullTabCheck] Map tab is unsupported. Removing it from full tab list."); cleanedTabs.Add(tab); continue; } if (StashUi.StashTabInfo.IsPremiumSpecial) { var controlsMetadata = tab.ControlsMetadata; var cleanedControls = new List <string>(); foreach (var metadata in controlsMetadata) { if (PremiumTabCanFit(metadata)) { GlobalLog.Warn($"[FullTabCheck] \"{tabName}\" tab is no longer full for \"{metadata}\"."); cleanedControls.Add(metadata); } else { GlobalLog.Warn($"[FullTabCheck] \"{tabName}\" tab is still full for \"{metadata}\"."); } } foreach (var cleaned in cleanedControls) { controlsMetadata.Remove(cleaned); } if (controlsMetadata.Count == 0) { GlobalLog.Warn($"[FullTabCheck] \"{tabName}\" tab does not contain any controls metadata. Removing it from full tab list."); cleanedTabs.Add(tab); } } else { if (StashUi.InventoryControl.Inventory.AvailableInventorySquares >= 8) { GlobalLog.Warn($"[FullTabCheck] \"{tabName}\" tab is no longer full."); cleanedTabs.Add(tab); } else { GlobalLog.Warn($"[FullTabCheck] \"{tabName}\" tab is still full."); } } } foreach (var tab in cleanedTabs) { Settings.Instance.FullTabs.Remove(tab); } return(true); }
public static async Task <bool> Execute(int range = -1) { var cachedMonsters = CombatAreaCache.Current.Monsters; if (CurrentTarget == null) { CurrentTarget = range == -1 ? cachedMonsters.ClosestValid() : cachedMonsters.ClosestValid(m => m.Position.Distance <= range); if (CurrentTarget == null) { return(false); } } if (Blacklist.Contains(CurrentTarget.Id)) { GlobalLog.Debug("[TrackMobLogic] Current target is in global blacklist. Now abandoning it."); CurrentTarget.Ignored = true; CurrentTarget = null; return(true); } var pos = CurrentTarget.Position; if (pos.IsFar || pos.IsFarByPath) { if (LogInterval.Elapsed) { GlobalLog.Debug($"[TrackMobTask] Cached monster locations: {cachedMonsters.Valid().Count()}"); GlobalLog.Debug($"[TrackMobTask] Moving to {pos}"); } if (!PlayerMoverManager.MoveTowards(pos)) { GlobalLog.Error($"[TrackMobTask] Fail to move to {pos}. Marking this monster as unwalkable."); CurrentTarget.Unwalkable = true; CurrentTarget = null; } return(true); } var monsterObj = CurrentTarget.Object as Monster; // Untested fix to not wait on a captured beast. Will be changed once confirmed issue is solved. //if (monsterObj == null || monsterObj.IsDead || (Loki.Game.LokiPoe.InstanceInfo.Bestiary.IsActive && (monsterObj.HasBestiaryCapturedAura || monsterObj.HasBestiaryDisappearingAura))) if (monsterObj == null || monsterObj.IsDead) { cachedMonsters.Remove(CurrentTarget); CurrentTarget = null; } else { var attempts = ++CurrentTarget.InteractionAttempts; if (attempts > MaxKillAttempts) { GlobalLog.Error("[TrackMobTask] All attempts to kill current monster have been spent. Now ignoring it."); CurrentTarget.Ignored = true; CurrentTarget = null; return(true); } GlobalLog.Debug($"[TrackMobTask] Alive monster is nearby, this is our {attempts}/{MaxKillAttempts} attempt to kill it."); await Coroutine.Sleep(200); } return(true); }
private static async Task ProcessShrine() { //check if current shrine was blacklisted by Combat Routine if (Blacklist.Contains(_shrine.Id)) { GlobalLog.Error("[OpenChestTask] Current shrine was blacklisted from outside."); _shrine.Ignored = true; _shrine = null; return; } var pos = _shrine.Position; if (Settings.ShrineOpenRange != -1) { if (pos.Distance > Settings.ShrineOpenRange * AbandonDistanceMult) { GlobalLog.Debug("[OpenChestTask] Abandoning current shrine because its too far away."); TemporaryIgnore(_shrine.Id); _shrine = null; return; } } if (pos.IsFar) { if (!pos.TryCome()) { GlobalLog.Error($"[OpenChestTask] Fail to move to {pos}. Marking this shrine as unwalkable."); _shrine.Unwalkable = true; _shrine = null; } return; } var shrineObj = _shrine.Object as Shrine; if (shrineObj == null || shrineObj.IsDeactivated) { CombatAreaCache.Current.Shrines.Remove(_shrine); _shrine = null; return; } var attempts = ++_shrine.InteractionAttempts; if (attempts > MaxShrineAttempts) { GlobalLog.Error("[OpenChestTask] All attempts to take a shrine have been spent. Now ignoring it."); _shrine.Ignored = true; _shrine = null; return; } if (await PlayerAction.Interact(shrineObj)) { await Wait.LatencySleep(); if (await Wait.For(() => shrineObj.IsDeactivated, "shrine deactivation", 100, 400)) { CombatAreaCache.Current.Shrines.Remove(_shrine); _shrine = null; } return; } await Wait.SleepSafe(400); }
private static async Task HandleCorruptedArea() { var cachedData = CachedData; if (cachedData.IsAreaFinished) { DisableEntrance(); var exit = LokiPoe.ObjectManager.Objects.Closest <AreaTransition>(a => a.IsTargetable); if (exit != null && await PlayerAction.TakeTransition(exit)) { return; } await PlayerAction.TpToTown(); return; } var vessel = cachedData.Vessel; if (vessel != null && cachedData.IsBossKilled) { var pos = vessel.Position; if (pos.IsFar || pos.IsFarByPath) { if (!pos.TryCome()) { GlobalLog.Error("[CorruptedAreaTask] Unexpected error. Vaal Vessel position is unwalkable."); cachedData.IsAreaFinished = true; } return; } var vesselObj = vessel.Object as Chest; if (vesselObj == null) { GlobalLog.Error("[CorruptedAreaTask] Unexpected error. Vaal Vessel object is null."); cachedData.IsAreaFinished = true; return; } var attempts = ++vessel.InteractionAttempts; if (attempts > 5) { GlobalLog.Error("[CorruptedAreaTask] All attempts to open Vaal Vessel have been spent."); cachedData.IsAreaFinished = true; return; } if (await PlayerAction.Interact(vesselObj, () => vesselObj.Fresh().IsOpened, "Vaal Vessel opening")) { await Wait.For(() => ExitExists, "corrupted area exit spawning", 500, 5000); } else { await Wait.SleepSafe(500); } return; } var boss = cachedData.Boss; if (boss != null) { var pos = boss.Position; if (pos.IsFar || pos.IsFarByPath) { if (!pos.TryCome()) { GlobalLog.Error("[CorruptedAreaTask] Unexpected error. Corrupted area boss is unwalkable."); cachedData.IsAreaFinished = true; } return; } var bossObj = boss.Object; if (bossObj == null) { GlobalLog.Warn("[CorruptedAreaTask] There is no boss object near cached position. Marking it as dead."); cachedData.IsBossKilled = true; return; } GlobalLog.Debug("[CorruptedAreaTask] Waiting for combat routine to kill the boss."); await Wait.StuckDetectionSleep(500); return; } if (!await CombatAreaCache.Current.Explorer.Execute()) { GlobalLog.Warn("[CorruptedAreaTask] Now leaving the corrupted area because it is fully explored."); cachedData.IsAreaFinished = true; } }
public async Task <bool> Run() { if (!World.CurrentArea.IsCombatArea) { return(false); } if (AbyssChest == null) { if ((AbyssChest = Abyss.CachedData.Chests.ClosestValid()) == null) { return(false); } } var pos = AbyssChest.Position; if (pos.IsFar || pos.IsFarByPath) { if (!pos.TryCome()) { GlobalLog.Error($"[OpenAbyssChest] Fail to move to {pos}. Abyssal Trove position is unwalkable."); AbyssChest.Unwalkable = true; AbyssChest = null; } return(true); } var chestObj = AbyssChest.Object as Chest; if (chestObj == null) { GlobalLog.Error("[OpenAbyssChest] Unexpected error. Chest object is null."); AbyssChest.Ignored = true; AbyssChest = null; return(true); } if (!chestObj.IsTargetable) { GlobalLog.Debug("[OpenAbyssChest] Waiting for Abyssal Trove activation."); await Wait.Sleep(500); return(true); } var attempts = ++AbyssChest.InteractionAttempts; if (attempts > MaxAttempts) { GlobalLog.Error($"[OpenAbyssChest] All attempts to interact with {pos.Name} have been spent. Now ignoring it."); AbyssChest.Ignored = true; AbyssChest = null; return(true); } if (await PlayerAction.Interact(chestObj, () => chestObj.Fresh().IsOpened, "Abyssal Trove opening", 1500)) { Abyss.CachedData.Chests.Remove(AbyssChest); AbyssChest = null; await Wait.Sleep(1500); BotStructure.TaskManager.GetTaskByName("LootItemTask")?.Message(new Message("ResetCurrentItem")); } else { await Wait.StuckDetectionSleep(500); } return(true); }
public async Task <bool> Run() { var area = World.CurrentArea; if (!area.IsTown && !area.IsHideoutArea) { return(false); } var itemsToId = new List <Vector2i>(); var itemFilter = ItemEvaluator.Instance; foreach (var item in Inventories.InventoryItems) { if (item.IsIdentified || item.IsCorrupted || item.IsMirrored) { continue; } if (!itemFilter.Match(item, EvaluationType.Id)) { continue; } itemsToId.Add(item.LocationTopLeft); } if (itemsToId.Count == 0) { GlobalLog.Info("[IdTask] No items to identify."); return(false); } GlobalLog.Info($"[IdTask] {itemsToId.Count} items to id."); int scrollsAmount = LokiPoe.InstanceInfo.GetPlayerInventoryBySlot(InventorySlot.Main).ItemAmount(CurrencyNames.Wisdom); if (scrollsAmount == 0 && Inventories.AvailableInventorySquares == 0) { GlobalLog.Error("[IdTask] No id scrolls and no free space in inventory. Now stopping the bot because it cannot continue."); BotManager.Stop(); return(true); } GlobalLog.Info($"[IdTask] {scrollsAmount} id scrolls."); if (scrollsAmount < itemsToId.Count) { GlobalLog.Warn("[IdTask] Not enough id scrolls to identify all items. Now going to take them from stash."); var result = await Inventories.WithdrawCurrency(CurrencyNames.Wisdom); if (result == WithdrawResult.Error) { ErrorManager.ReportError(); return(true); } if (result == WithdrawResult.Unavailable) { GlobalLog.Error("[IdTask] There are no id scrolls in all tabs assigned to them. Now stopping the bot because it cannot continue."); BotManager.Stop(); return(true); } } if (!await Inventories.OpenInventory()) { ErrorManager.ReportError(); return(true); } itemsToId.Sort(Position.Comparer.Instance); foreach (var pos in itemsToId) { if (!await Identify(pos)) { ErrorManager.ReportError(); return(true); } } await Coroutines.CloseBlockingWindows(); return(true); }
public async Task <bool> Run() { if (ErrorLimitReached) { return(false); } var area = World.CurrentArea; if (!area.IsTown && !area.IsHideoutArea) { return(false); } var errors = GetUserErrors(); if (errors.Count > 0) { foreach (var error in errors) { GlobalLog.Error(error); } BotManager.Stop(); return(true); } var currencyToRestock = new List <string>(); foreach (var currency in Settings.Instance.InventoryCurrencies) { var name = currency.Name; var restock = currency.Restock; if (restock < 0) { continue; } GetCurrentAndMaxStackCount(name, out var count, out var maxStackCount); if (restock >= maxStackCount) { GlobalLog.Error($"[InventoryCurrency] Invalid restock value for \"{name}\". Restock: {restock}. Max stack count: {maxStackCount}."); GlobalLog.Error("[InventoryCurrency] Restock value must be less than item's max stack count. Please correct your settings."); BotManager.Stop(); return(true); } if (count > restock) { continue; } if (Unavailable.Contains(name)) { GlobalLog.Debug($"[CurrencyRestockTask] Skipping \"{name}\" restock because it is marked as unavailable."); continue; } GlobalLog.Debug($"[CurrencyRestockTask] Restock is needed for \"{name}\". Current count: {count}. Count to restock: {restock}."); currencyToRestock.Add(name); } if (currencyToRestock.Count == 0) { GlobalLog.Info("[CurrencyRestockTask] No currency to restock."); return(false); } foreach (var currency in currencyToRestock) { GlobalLog.Debug($"[CurrencyRestockTask] Now going to restock \"{currency}\"."); var result = await Inventories.WithdrawCurrency(currency); if (result == WithdrawResult.Error) { ReportError(); return(true); } if (result == WithdrawResult.Unavailable) { GlobalLog.Warn($"[CurrencyRestockTask] There are no \"{currency}\" in all tabs assigned to them. Now marking this currency as unavailable."); Unavailable.Add(currency); } } await Coroutines.CloseBlockingWindows(); return(true); }
public async Task <bool> Run() { if (!settings.Instance.ExaltRecipeEnabled) { return(false); } if (_shaperStashTabIsFull || ErrorLimitReached) { return(false); } var area = World.CurrentArea; if (!area.IsTown && !area.IsHideoutArea) { return(false); } if (_shouldUpdateStashData) { GlobalLog.Debug("[StashRecipeTask] Updating shaper exalt recipe stash data (every Start)"); if (settings.Instance.ExaltRecipeEnabled) { if (!await OpenShaperRecipeTab()) { return(true); } else { Class1.ShaperStashData.SyncWithStashTab(RecipeData.ExaltRecipeItemType.Shaper); } } _shouldUpdateStashData = false; } else { if (AnyItemToStash) { GlobalLog.Debug("[StashRecipeTask] Updating shaper exalt recipe stash data before actually stashing the items."); if (settings.Instance.ExaltRecipeEnabled) { if (!await OpenShaperRecipeTab()) { return(true); } else { Class1.ShaperStashData.SyncWithStashTab(RecipeData.ExaltRecipeItemType.Shaper); } } } else { GlobalLog.Info("[StashRecipeTask] AnyItemsToStash empty, No items to stash for shaper exalt recipe."); await Coroutines.CloseBlockingWindows(); return(false); } } var itemsToStash = ItemsToStash; if (itemsToStash.Count == 0) { GlobalLog.Info("[StashRecipeTask] No items to stash for shaper exalt recipe."); await Coroutines.CloseBlockingWindows(); return(false); } GlobalLog.Info($"[StashRecipeTask] {itemsToStash.Count} items to stash for shaper exalt recipe."); await OpenShaperRecipeTab(); // Shaper Loop foreach (var item in itemsToStash.OrderBy(i => i.Position, Position.Comparer.Instance)) { if (item.RecipeType != RecipeData.ExaltRecipeItemType.Shaper) { continue; } GlobalLog.Debug($"[StashRecipeTask] Now stashing \"{item.Name}\" for shaper exalt recipe."); var itemPos = item.Position; if (!Inventories.StashTabCanFitItem(itemPos)) { GlobalLog.Error("[StashRecipeTask] Stash tab for shaper exalt recipe is full and must be cleaned."); _shaperStashTabIsFull = true; return(true); } if (!await Inventories.FastMoveFromInventory(itemPos)) { ReportError(); return(true); } Class1.ShaperStashData.IncreaseItemCount(item.ItemType); GlobalLog.Info($"[Events] Item stashed ({item.FullName})"); Utility.BroadcastMessage(this, Events.Messages.ItemStashedEvent, item); } await Wait.SleepSafe(300); Class1.ShaperStashData.SyncWithStashTab(RecipeData.ExaltRecipeItemType.Shaper); Class1.ShaperStashData.Log(); return(true); }
public async Task <bool> Run() { var area = World.CurrentArea; if (!area.IsMap && !area.IsOverworldArea) { return(false); } if (LokiPoe.InstanceInfo.Incursion.IncursionsRemaining != 0) { return(false); } var cache = CombatAreaCache.Current; if (cache.Storage["IsTempleCompleted"] != null) { return(false); } var alva = Incursion.CachedAlva; if (alva == null || alva.Unwalkable || alva.Ignored) { return(false); } var pos = alva.Position; if (pos.Distance > 20 || pos.PathDistance > 20) { if (!pos.TryCome()) { GlobalLog.Error($"[EnterTempleTask] Fail to move to {pos}. Alva is unwalkable."); alva.Unwalkable = true; } return(true); } var alvaObj = alva.Object; if (alvaObj == null) { GlobalLog.Error("[EnterTempleTask] Unexpected error. We are near cached Alva, but actual object is null."); alva.Ignored = true; return(true); } var portal = ActiveTemplePortal; if (portal == null) { var attempts = ++alva.InteractionAttempts; if (attempts > 7) { GlobalLog.Error("[EnterTempleTask] All attempts to interact with Alva have been spent."); alva.Ignored = true; return(true); } if (alvaObj.HasNpcFloatingIcon) { if (await PlayerAction.Interact(alvaObj)) { await Wait.Sleep(200); await Coroutines.CloseBlockingWindows(); } return(true); } if (await alvaObj.AsTownNpc().Converse("Enter Temple")) { await Coroutines.CloseBlockingWindows(); await Wait.For(() => ActiveTemplePortal != null, "Temple portals activation", 500, 10000); } return(true); } if (Settings.Instance.SkipTemple) { cache.Storage["IsTempleCompleted"] = true; return(true); } if (ErrorManager.GetErrorCount("EnterTemple") >= 5) { GlobalLog.Error("[EnterTempleTask] Failed to enter Temple portal 5 times."); alva.Ignored = true; return(true); } if (!await PlayerAction.TakePortal(portal)) { ErrorManager.ReportError("EnterTemple"); await Wait.SleepSafe(500); } return(true); }
public async Task <bool> Run() { if (ErrorLimitReached) { return(false); } var area = World.CurrentArea; if (!area.IsTown && !area.IsHideoutArea) { return(false); } if (_shouldUpdateStashData) { GlobalLog.Debug("[SellExtraMapsTask] Updating map tab stash data (every Start)"); if (!await OpenMapTab()) { return(true); } else { Class1.MapStashData.SyncWithStashTab(); } _shouldUpdateStashData = false; } else { if (!await Inventories.OpenStashTab(settings.Instance.MapStashTab)) { ReportError(); return(true); } Class1.MapStashData.SyncWithStashTab(); if (Class1.MapStashData.GetMapCount() > settings.Instance.MaxNumMaps) { var mapsInStashTab = Inventories.StashTabItems .Where(m => m.IsMap() && m.Rarity != Rarity.Unique) .OrderBy(m => m.Priority()) .ThenBy(m => m.MapTier).Take(settings.Instance.SellNumMaps); foreach (var mapItem in mapsInStashTab) { if (!await Inventories.FastMoveFromStashTab(mapItem.LocationTopLeft)) { ReportError(); return(true); } } await Wait.SleepSafe(300); Class1.MapStashData.SyncWithStashTab(); var mapSellItems = Inventories.InventoryItems .Where(m => m.IsMap()) .Select(i => i.LocationTopLeft) .ToList(); if (mapSellItems.Count == 0) { GlobalLog.Error("[SellExtraMapsTask] Unknown error. There are no map items in player's inventory after taking them from stash."); ReportError(); return(true); } if (!await TownNpcs.SellItems(mapSellItems)) { ReportError(); } } else { return(false); } } return(true); }
public async Task <bool> Run() { if (MapBot.IsOnRun) { return(false); } var area = World.CurrentArea; if (!area.IsTown && !area.IsHideoutArea) { return(false); } MapExtensions.AtlasData.Update(); if (!Settings.SellEnabled) { return(false); } if (Inventories.AvailableInventorySquares < 3) { GlobalLog.Error("[SellMapTask] Not enough inventory space."); return(false); } var firstMapTab = ExSettings.Instance.GetTabsForCategory(ExSettings.StashingCategory.Map).First(); if (!await Inventories.OpenStashTab(firstMapTab)) { GlobalLog.Error($"[SellMapTask] Fail to open stash tab \"{firstMapTab}\"."); return(false); } var maps = Inventories.StashTabItems .Where(m => m.IsMap() && m.ShouldSell()) .OrderBy(m => m.Priority()) .ThenBy(m => m.MapTier) .ToList(); if (maps.Count == 0) { return(false); } var mapGroups = new List <Item[]>(); foreach (var mapGroup in maps.GroupBy(m => m.Name)) { var groupList = mapGroup.ToList(); for (int i = 3; i <= groupList.Count; i += 3) { var group = new Item[3]; group[0] = groupList[i - 3]; group[1] = groupList[i - 2]; group[2] = groupList[i - 1]; mapGroups.Add(group); } } if (mapGroups.Count == 0) { GlobalLog.Info("[SellMapTask] No map group for sale was found."); return(false); } GlobalLog.Info($"[SellMapTask] Map groups for sale: {mapGroups.Count}"); foreach (var mapGroup in mapGroups) { if (Inventories.AvailableInventorySquares < 3) { GlobalLog.Error("[SellMapTask] Not enough inventory space."); break; } //exclude ignored maps from min map amount check, if sell ignored maps is enabled if (!Settings.SellIgnoredMaps || !mapGroup[0].Ignored()) { int mapAmount = Inventories.StashTabItems.Count(i => i.IsMap() && i.Rarity != Rarity.Unique); if ((mapAmount - 3) < Settings.MinMapAmount) { GlobalLog.Warn($"[SellMapTask] Min map amount is reached {mapAmount}(-3) from required {Settings.MinMapAmount}"); break; } } for (int i = 0; i < 3; i++) { var map = mapGroup[i]; GlobalLog.Info($"[SellMapTask] Now getting {i + 1}/{3} \"{map.Name}\"."); if (!await Inventories.FastMoveFromStashTab(map.LocationTopLeft)) { ErrorManager.ReportError(); return(true); } } } await Wait.SleepSafe(200); var forSell = Inventories.InventoryItems.Where(i => i.IsMap()).Select(m => m.LocationTopLeft).ToList(); if (forSell.Count == 0) { return(false); } if (!await TownNpcs.SellItems(forSell)) { ErrorManager.ReportError(); } return(true); }
private async Task EnterTransition() { var pos = _transition.Position; if (pos.IsFar) { if (!pos.TryCome()) { GlobalLog.Debug($"[ComplexExplorer] Fail to move to {pos}. Marking this transition as unwalkable."); _transition.Unwalkable = true; _transition = null; } return; } var transitionObj = _transition.Object; if (transitionObj == null) { GlobalLog.Error("[ComplexExplorer] Unknown error. There is no transition near cached position."); _transition.Ignored = true; _transition = null; return; } if (!transitionObj.IsTargetable) { if (transitionObj.Metadata.Contains("sarcophagus_transition")) { if (await HandleSarcophagus() && transitionObj.Fresh().IsTargetable) { return; } } if (_transition.InteractionAttempts >= MaxTransitionAttempts) { GlobalLog.Error("[ComplexExplorer] Area transition did not become targetable. Now ignoring it."); _transition.Ignored = true; _transition = null; return; } var attempts = ++_transition.InteractionAttempts; GlobalLog.Debug($"[ComplexExplorer] Waiting for \"{pos.Name}\" to become targetable ({attempts}/{MaxTransitionAttempts})"); await Wait.SleepSafe(1000); return; } _disableTick = true; if (!await PlayerAction.TakeTransition(transitionObj)) { var attempts = ++_transition.InteractionAttempts; GlobalLog.Error($"[ComplexExplorer] Fail to enter {pos}. Attempt: {attempts}/{MaxTransitionAttempts}"); if (attempts >= MaxTransitionAttempts) { GlobalLog.Error("[ComplexExplorer] All attempts to enter an area transition have been spent. Now ignoring it."); _transition.Ignored = true; _transition = null; } else { await Wait.SleepSafe(500); } } else { PostEnter(); GlobalLog.Info("[ComplexExplorer] LocalTransitionEntered event."); LocalTransitionEntered?.Invoke(); Utility.BroadcastMessage(this, LocalTransitionEnteredMessage); if (Settings.OpenPortals) { GlobalLog.Info("[ComplexExplorer] Opening a portal."); await PlayerAction.CreateTownPortal(); } } _disableTick = false; }