private static void OnLocalTransitionEntered() { GlobalLog.Info("[CombatAreaCache] Resetting unwalkable flags on all cached objects."); var cache = Current; foreach (var item in cache.Items) { item.Unwalkable = false; } foreach (var monster in cache.Monsters) { monster.Unwalkable = false; } foreach (var chest in cache.Chests) { chest.Unwalkable = false; } foreach (var specialChest in cache.SpecialChests) { specialChest.Unwalkable = false; } foreach (var strongbox in cache.Strongboxes) { strongbox.Unwalkable = false; } foreach (var shrine in cache.Shrines) { shrine.Unwalkable = false; } foreach (var transition in cache.AreaTransitions) { transition.Unwalkable = false; } }
private static void DoorScan(IncursionData data) { foreach (var door in IncursionDoors) { var targetable = door.IsTargetable; var id = door.Id; var index = data.Doors.FindIndex(d => d.Id == id); if (index >= 0) { if (!targetable) { GlobalLog.Info($"[HandleIncursionTask] Removing opened {door.WalkablePosition()}"); data.Doors.RemoveAt(index); } } else { if (targetable) { var pos = door.WalkablePosition(); GlobalLog.Warn($"[HandleIncursionTask] Registering {pos}"); data.Doors.Add(new CachedObject(id, pos)); } } } }
public MessageResult Message(Loki.Bot.Message message) { var id = message.Id; if (id == Events.Messages.ItemStashedEvent) { var itemName = message.GetInput <CachedItem>()?.Name; if (!_hasWhiteSextants && itemName == CurrencyNames.SextantApprentice) { GlobalLog.Info("[SextantTask] Apprentice Sextant has been stashed. Now marking them as available."); _hasWhiteSextants = true; return(MessageResult.Processed); } if (!_hasYellowSextants && itemName == CurrencyNames.SextantJourneyman) { GlobalLog.Info("[SextantTask] Journeyman Sextant has been stashed. Now marking them as available."); _hasYellowSextants = true; return(MessageResult.Processed); } if (!_hasRedSextants && itemName == CurrencyNames.SextantMaster) { GlobalLog.Info("[SextantTask] Master Sextant has been stashed. Now marking them as available."); _hasRedSextants = true; return(MessageResult.Processed); } return(MessageResult.Unprocessed); } if (id == Events.Messages.CombatAreaChanged) { ResetErrors(); return(MessageResult.Processed); } return(MessageResult.Unprocessed); }
public override void OnStashing(CachedItem item) { if (_tabWithGcpSet != null || item.Type.ItemType != ItemTypes.Gem || item.Quality < 1) { return; } var qualities = GemQualitiesInCurrentTab; if (qualities.Count == 0) { return; } var finder = new GemSetFinder(qualities); _gcpSet = finder.BestSet; if (_gcpSet != null) { GlobalLog.Info($"[OnQGemStash] Found gem set for gcp recipe {_gcpSet}"); _tabWithGcpSet = LokiPoe.InGameState.StashUi.TabControl.CurrentTabName; } else { GlobalLog.Info("[OnQGemStash] Gem set for gcp recipe was not found."); } }
public MessageResult Message(Message message) { var id = message.Id; if (id == MapBot.Messages.NewMapEntered) { GlobalLog.Info("[SpecialObjectTask] Reset."); Reset(message.GetInput <string>()); if (_enabled) { GlobalLog.Info("[SpecialObjectTask] Enabled."); } return(MessageResult.Processed); } if (id == ComplexExplorer.LocalTransitionEnteredMessage) { GlobalLog.Info("[SpecialObjectTask] Resetting unwalkable flags."); foreach (var speacialObj in Objects) { speacialObj.Unwalkable = false; } return(MessageResult.Processed); } return(MessageResult.Unprocessed); }
public MessageResult Message(Message message) { var id = message.Id; if (id == MapBot.Messages.NewMapEntered) { GlobalLog.Info("[KillBossTask] Reset."); var areaName = message.GetInput <string>(); _bossesKilled = 0; _currentTarget = null; BossKilled = false; _multiPhaseBoss = false; _teleportingBoss = false; CachedBosses.Clear(); SetBossSelector(areaName); SetPriorityBossName(areaName); SetBossRange(areaName); if (areaName == MapNames.VaultsOfAtziri) { BossKilled = true; GlobalLog.Info($"[KillBossTask] BossKilled is set to true ({areaName})"); return(MessageResult.Processed); } if (areaName == MapNames.MineralPools || areaName == MapNames.Palace || areaName == MapNames.Basilica || areaName == MapNames.MaelstromOfChaos) { _multiPhaseBoss = true; GlobalLog.Info($"[KillBossTask] MultiPhaseBoss is set to true ({areaName})"); return(MessageResult.Processed); } if (areaName == MapNames.Pen || areaName == MapNames.Pier || areaName == MapNames.Shrine || areaName == MapNames.DesertSpring || areaName == MapNames.Summit || areaName == MapNames.DarkForest || areaName == MapNames.PutridCloister) { _teleportingBoss = true; GlobalLog.Info($"[KillBossTask] TeleportingBoss is set to true ({areaName})"); return(MessageResult.Processed); } return(MessageResult.Processed); } if (id == ComplexExplorer.LocalTransitionEnteredMessage) { GlobalLog.Info("[KillBossTask] Resetting unwalkable flags."); foreach (var cachedBoss in CachedBosses) { cachedBoss.Unwalkable = false; } return(MessageResult.Processed); } return(MessageResult.Unprocessed); }
public MessageResult Message(Message message) { var id = message.Id; if (id == MapBot.Messages.NewMapEntered) { GlobalLog.Info("[ProximityTriggerTask] Reset."); Reset(message.GetInput <string>()); if (_triggerMetadata != null) { GlobalLog.Info("[ProximityTriggerTask] Enabled."); } return(MessageResult.Processed); } if (id == ComplexExplorer.LocalTransitionEnteredMessage) { if (_trigger != null) { GlobalLog.Info("[ProximityTriggerTask] Resetting unwalkable flag."); _trigger.Unwalkable = false; } return(MessageResult.Processed); } return(MessageResult.Unprocessed); }
public override async Task Execute() { CurrencyToBuy.Sort((c1, c2) => ExchangePriority[c1.Name].CompareTo(ExchangePriority[c2.Name])); var currency = CurrencyToBuy[0]; GlobalLog.Info($"[VendorTask] Now going to buy {currency.Amount} {currency.Name}."); if (!CanBuyInCurrentArea(currency.Name)) { var exchangeArea = GetExchangeArea(); if (exchangeArea == null) { GlobalLog.Warn($"[VendorTask] Cannot exchange \"{currency.Name}\" in current area and Act 3 has not been opened yet."); ResetData(); return; } if (!await PlayerAction.TakeWaypoint(exchangeArea)) { ReportError(); return; } } if (!await CurrencyPurchase(currency)) { ReportError(); } }
public static MapData LoadFromJson(string path) { var data = new MapData(); if (!File.Exists(path)) { return(data); } var json = File.ReadAllText(path); if (string.IsNullOrWhiteSpace(json)) { GlobalLog.Info("[MapManager] Fail to load stash data from json. File is empty."); return(data); } int[] jsonCounts; try { jsonCounts = JsonConvert.DeserializeObject <int[]>(json); } catch (Exception) { GlobalLog.Info("[MapManager] Fail to load stash data from json. Exception during json deserialization."); return(data); } if (jsonCounts == null) { GlobalLog.Info("[MapManager] Fail to load stash data from json. Json deserealizer returned null."); return(data); } Array.Copy(jsonCounts, data._counts, data._counts.Length); return(data); }
public void Log() { var sb = new StringBuilder("[FlaskInfo] Flags: "); foreach (var p in GetType().GetFields()) { if (p.FieldType != typeof(bool)) { continue; } var value = (bool)p.GetValue(this); if (value) { sb.Append($"{p.Name}, "); } } sb.Length -= 2; sb.Append('.'); GlobalLog.Info(sb.ToString()); foreach (var flask in TriggerFlasks) { foreach (var trigger in flask.Triggers) { GlobalLog.Info($"[{flask.Name}] {trigger}."); } } }
private static void Reset(string areaName) { _triggerMetadata = null; _trigger = null; _waitCount = 0; if (MapData.Current.IgnoredBossroom) { GlobalLog.Info("[TransitionTriggerTask] Skipping this task because bossroom is ignored."); return; } if (areaName == MapNames.Academy || areaName == MapNames.Museum || areaName == MapNames.Scriptorium) { _triggerMetadata = "Metadata/QuestObjects/Library/HiddenDoorTrigger"; return; } if (areaName == MapNames.Necropolis) { _triggerMetadata = "Metadata/Chests/Sarcophagi/sarcophagus_door"; return; } if (areaName == MapNames.WastePool) { _triggerMetadata = "Metadata/QuestObjects/Sewers/SewersGrate"; } }
public async Task <bool> Run() { if (!World.CurrentArea.IsMap) { return(false); } await Coroutines.FinishCurrentAction(); var maxPulses = MaxPulses; if (_pulse < maxPulses) { ++_pulse; GlobalLog.Info($"[FinishMapTask] Final pulse {_pulse}/{maxPulses}"); await Wait.SleepSafe(500); return(true); } GlobalLog.Warn("[FinishMapTask] Now leaving current map."); if (!await PlayerAction.TpToTown()) { ErrorManager.ReportError(); return(true); } MapBot.IsOnRun = false; Statistics.Instance.OnMapFinish(); GlobalLog.Info("[MapBot] MapFinished event."); Utility.BroadcastMessage(this, MapBot.Messages.MapFinished); return(true); }
private CombatAreaCache(uint hash) { GlobalLog.Info($"[CombatAreaCache] Creating cache for \"{World.CurrentArea.Name}\" (hash: {hash})"); Hash = hash; WorldArea = World.CurrentArea; Explorer = new ComplexExplorer(); _lastAccessTime = Stopwatch.StartNew(); }
private static void OnItemEvaluatorRefresh(object sender, ItemEvaluatorRefreshedEventArgs args) { if (Caches.TryGetValue(LokiPoe.LocalData.AreaHash, out var cache)) { GlobalLog.Info("[CombatAreaCache] Clearing processed items."); cache._processedItems.Clear(); } }
private static async Task <bool> TakeGcpSets() { if (!await Inventories.OpenStashTab(_tabWithGcpSet)) { return(false); } while (true) { if (_gcpSet == null) { var qualities = GemQualitiesInCurrentTab; if (qualities.Count == 0) { GlobalLog.Info($"[TakeGcpSets] No quality gems were found in \"{_tabWithGcpSet}\" tab."); _tabWithGcpSet = null; return(true); } var finder = new GemSetFinder(qualities); _gcpSet = finder.BestSet; if (_gcpSet == null) { GlobalLog.Info($"[TakeGcpSets] No more gem sets for gcp recipe were found in \"{_tabWithGcpSet}\" tab."); _tabWithGcpSet = null; return(true); } } if (!_gcpSet.CanFit) { GlobalLog.Warn("[TakeGcpSets] Not enough inventory space for current gcp set."); _gcpSet = null; return(true); } GlobalLog.Warn($"[TakeGcpSets] Now taking gcp set {_gcpSet}"); foreach (int q in _gcpSet.Qualities) { var gem = StashGems.FirstOrDefault(g => QGemFitsForSelling(g) && g.Quality == q); if (gem == null) { GlobalLog.Error($"[TakeGcpSets] Unexpected error. Fail to find gem with quality {q} as a part of {_gcpSet} gcp set."); _tabWithGcpSet = null; _gcpSet = null; return(false); } if (!await Inventories.FastMoveFromStashTab(gem.LocationTopLeft)) { return(false); } } _gcpSet = null; } }
private static async Task <bool> ExchangeCard(Vector2i cardPos) { if (!ExchangeUi.IsOpened) { if (!await OpenExchangeUi()) { return(false); } } var card = LokiPoe.InGameState.InventoryUi.InventoryControl_Main.Inventory.FindItemByPos(cardPos); if (card == null) { GlobalLog.Error($"[ExchangeCard] Fail to find item at {cardPos}."); return(false); } var cardName = card.Name; GlobalLog.Info($"[ExchangeCard] Now exchanging \"{cardName}\"."); if (!await Inventories.FastMoveFromInventory(cardPos)) { return(false); } if (!await Wait.For(() => ExchangeUiItem != null, "divination card appear in ExchangeUi")) { return(false); } // similar to Map Device UI, sometimes Activate button needs extra time to become clickable. await Wait.SleepSafe(200); var id = ExchangeUiItem.LocalId; var activated = ExchangeUi.Activate(); if (activated != LokiPoe.InGameState.ActivateResult.None) { GlobalLog.Error($"[ExchangeCard] Fail to activate the ExchangeUi. Error: \"{activated}\"."); return(false); } if (!await Wait.For(() => { var item = ExchangeUiItem; return(item != null && item.LocalId != id); }, "divination card exchanging")) { return(false); } WriteToLog(cardName, ExchangeUiItem); return(true); }
public static bool AddSettingsProvider(string ownerId, Func <ExplorationSettings> getSettings, ProviderPriority priority) { if (!SettingsProviders.Exists(s => s.OwnerId == ownerId)) { SettingsProviders.Add(new SettingsProvider(ownerId, getSettings, priority)); GlobalLog.Info($"[ComplexExplorer] {ownerId} settings provider has been added."); return(true); } return(false); }
private static void RemoveOldCaches() { var toRemove = Caches.Where(c => c.Value._lastAccessTime.Elapsed > Lifetime).Select(c => c.Value).ToList(); foreach (var cache in toRemove) { GlobalLog.Info($"[CombatAreaCache] Removing cache for \"{cache.WorldArea.Name}\" (hash: {cache.Hash}). Last accessed {(int) cache._lastAccessTime.Elapsed.TotalMinutes} minutes ago."); Caches.Remove(cache.Hash); } }
public override async Task Execute() { var area = GetCardExchangeArea(); if (area == null) { GlobalLog.Warn("[VendorTask] Divination card exchange is not possible because this character has no access to Highgate and we are not in hideout."); ResetData(); return; } if (_itemLeftInExchangeUi) { GlobalLog.Warn("[VendorTask] Item was left in ExchangeUi. Now going to take it."); if (!area.IsCurrentArea) { if (!await PlayerAction.TakeWaypoint(area)) { ReportError(); return; } } if (!await TakeItemFromExchangeUi()) { ReportError(); } return; } GlobalLog.Info("[VendorTask] Now going to exchange divination cards."); if (!await TakeCards()) { ReportError(); return; } if (!area.IsCurrentArea) { if (!await PlayerAction.TakeWaypoint(area)) { ReportError(); return; } } if (!await ExchangeCards()) { ReportError(); } }
public MessageResult Message(Message message) { if (message.Id == MapBot.Messages.NewMapEntered) { GlobalLog.Info("[EnterTrialTask] Reset."); _trial = null; _enabled = true; return(MessageResult.Processed); } return(MessageResult.Unprocessed); }
public void Log() { GlobalLog.Info($"[ChaosRecipe] Weapons: {GetItemCount(RecipeItemType.Weapon)}"); GlobalLog.Info($"[ChaosRecipe] Body armors: {GetItemCount(RecipeItemType.BodyArmor)}"); GlobalLog.Info($"[ChaosRecipe] Helmets: {GetItemCount(RecipeItemType.Helmet)}"); GlobalLog.Info($"[ChaosRecipe] Boots: {GetItemCount(RecipeItemType.Boots)}"); GlobalLog.Info($"[ChaosRecipe] Gloves: {GetItemCount(RecipeItemType.Gloves)}"); GlobalLog.Info($"[ChaosRecipe] Belts: {GetItemCount(RecipeItemType.Belt)}"); GlobalLog.Info($"[ChaosRecipe] Amulets: {GetItemCount(RecipeItemType.Amulet)}"); GlobalLog.Info($"[ChaosRecipe] Rings: {GetItemCount(RecipeItemType.Ring)}"); }
public static bool RemoveSettingsProvider(string ownerId) { var index = SettingsProviders.FindIndex(s => s.OwnerId == ownerId); if (index >= 0) { SettingsProviders.RemoveAt(index); GlobalLog.Info($"[ComplexExplorer] {ownerId} settings provider has been removed."); return(true); } return(false); }
private static async Task <bool> ExchangeCards() { var cardPositions = Inventories.InventoryItems .Where(ItemIsCardSet) .Select(c => c.LocationTopLeft) .ToList(); if (cardPositions.Count == 0) { GlobalLog.Error("[ExchangeCards] Fail to find any complete divination set in inventory."); return(false); } cardPositions.Sort(Position.Comparer.Instance); GlobalLog.Info($"[ExchangeCards] Now going to exchange {cardPositions.Count} divination card sets."); if (!ExchangeUi.IsOpened) { if (!await OpenExchangeUi()) { return(false); } } if (ExchangeUiItem != null) { if (!await TakeItemFromExchangeUi()) { return(false); } } foreach (var cardPos in cardPositions) { if (_itemLeftInExchangeUi) { break; } if (!await ExchangeCard(cardPos)) { return(false); } if (!await TakeItemFromExchangeUi()) { return(false); } } return(true); }
private static ExplorationSettings ProvideSettings() { foreach (var provider in SettingsProviders.OrderBy(p => p.Priority)) { var settings = provider.GetSettings(); if (settings != null) { GlobalLog.Info($"[ComplexExplorer] Exploration settings provided by {provider.OwnerId}."); return(settings); } } GlobalLog.Info("[ComplexExplorer] Exploration settings was not provided. Using default."); return(new ExplorationSettings()); }
private static async Task Click() { StuckDetection.Reset(); await Wait.LatencySleep(); var target = LokiPoe.InGameState.CurrentTarget; if (target != null) { GlobalLog.Info($"[HandleBlockingChestsTask] \"{target.Name}\" ({target.Id}) is under the cursor. Now clicking on it."); LokiPoe.Input.PressLMB(); await Coroutines.FinishCurrentAction(false); } }
public MessageResult Message(Message message) { if (message.Id == MapBot.Messages.NewMapEntered) { _range = -1; var areaName = message.GetInput <string>(); if (areaName == MapNames.MaoKun) { MapData.Current.TrackMob = true; GlobalLog.Info("[MapExplorationTask] Monster Tracking is hard enabled for this map."); } return(MessageResult.Processed); } return(MessageResult.Unprocessed); }
public static async Task <bool> RerollRare(Vector2i mapPos) { while (true) { var map = InventoryUi.InventoryControl_Main.Inventory.FindItemByPos(mapPos); if (map == null) { GlobalLog.Error($"[RerollRare] Fail to find a map at {mapPos}."); return(false); } var rarity = map.RarityLite(); if (rarity != Rarity.Rare) { GlobalLog.Error($"[TakeMapTask] RerollRare is called on {rarity} map."); return(false); } var affix = map.GetBannedAffix(); if (affix == null) { return(true); } GlobalLog.Info($"[RerollRare] Rerolling banned \"{affix}\" affix."); if (Settings.RerollMethod == RareReroll.Chaos) { if (!await ApplyOrb(mapPos, CurrencyNames.Chaos)) { return(false); } } else { if (!await ApplyOrb(mapPos, CurrencyNames.Scouring)) { return(false); } if (!await ApplyOrb(mapPos, CurrencyNames.Alchemy)) { return(false); } } } }
public MessageResult Message(Message message) { if (message.Id == MapBot.Messages.NewMapEntered) { GlobalLog.Info("[TransitionTriggerTask] Reset."); Reset(message.GetInput <string>()); if (_triggerMetadata != null) { GlobalLog.Info("[TransitionTriggerTask] Enabled."); } return(MessageResult.Processed); } return(MessageResult.Unprocessed); }
public static async Task <bool> InitializeMaxSextants() { if (!await OpenAtlasUi()) { return(false); } _maxSextants = LokiPoe.InGameState.AtlasUi.MaxSextants; GlobalLog.Info($"[SextantTask] MaxSextants: {_maxSextants}"); if (!await CloseAtlasUi()) { return(false); } return(true); }
private static void SetBossSelector(string areaName) { if (areaName == MapNames.Precinct) { GlobalLog.Info("[KillBossTask] This map has a group of Rogue Exiles as map bosses."); _isMapBoss = m => m.Rarity == Rarity.Unique && m.Metadata.Contains("MapBoss"); return; } if (areaName == MapNames.Courthouse) { GlobalLog.Info("[KillBossTask] This map has a group of dark Rogue Exiles as map bosses."); _isMapBoss = m => m.Rarity == Rarity.Unique && m.Metadata.EndsWith("Kitava") && m.Metadata.Contains("/Exiles/"); return; } if (areaName == MapNames.InfestedValley) { GlobalLog.Info("[KillBossTask] Nests have to be killed to activate boss on this map."); _isMapBoss = m => m.IsMapBoss || m.Name == "Gorulis' Nest"; return; } if (areaName == MapNames.Siege) { GlobalLog.Info("[KillBossTask] Totems must be killed to remove boss immunity on this map."); _isMapBoss = m => m.IsMapBoss || m.Name == "Tukohama's Protection"; return; } if (areaName == MapNames.WhakawairuaTuahu) { GlobalLog.Info("[KillBossTask] This map has Shade of a player as one of the map bosses."); _isMapBoss = m => m.IsMapBoss || (m.Rarity == Rarity.Unique && m.Metadata.Contains("DarkExile")); return; } if (areaName == MapNames.Shipyard || areaName == MapNames.Lighthouse || areaName == MapNames.Iceberg || areaName == MapNames.AcidLakes) { GlobalLog.Info("[KillBossTask] This map has a Warband leader as a map boss."); _isMapBoss = m => m.Rarity == Rarity.Unique && m.ExplicitAffixes.Any(a => a.InternalName == "MonsterWbLeader"); return; } _isMapBoss = DefaultBossSelector; }