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 async Task <bool> Run() { if (BossKilled || MapExplorationTask.MapCompleted) { return(false); } var area = World.CurrentArea; if (!area.IsMap) { return(false); } if (_currentTarget == null) { if ((_currentTarget = CachedBosses.ClosestValid(b => !b.IsDead)) == null) { return(false); } } if (Blacklist.Contains(_currentTarget.Id)) { GlobalLog.Warn("[KillBossTask] Boss is in global blacklist. Now marking it as killed."); _currentTarget.IsDead = true; _currentTarget = null; RegisterDeath(); return(true); } if (_priorityBossName != null && _currentTarget.Position.Name != _priorityBossName) { var priorityBoss = CachedBosses.ClosestValid(b => !b.IsDead && b.Position.Name == _priorityBossName); if (priorityBoss != null) { GlobalLog.Debug($"[KillBossTask] Switching current target to \"{priorityBoss}\"."); _currentTarget = priorityBoss; return(true); } } if (_currentTarget.IsDead) { var newBoss = CachedBosses.Valid().FirstOrDefault(b => !b.IsDead); if (newBoss != null) { _currentTarget = newBoss; } } var pos = _currentTarget.Position; if (pos.Distance <= 50 && pos.PathDistance <= 55) { var bossObj = _currentTarget.Object as Monster; if (bossObj == null) { if (_teleportingBoss) { CachedBosses.Remove(_currentTarget); _currentTarget = null; return(true); } GlobalLog.Debug("[KillBossTask] We are close to last know position of map boss, but boss object does not exist anymore."); GlobalLog.Debug("[KillBossTask] Most likely this boss does not spawn a corpse or was shattered/exploded."); _currentTarget.IsDead = true; _currentTarget = null; RegisterDeath(); return(true); } } if (pos.Distance > _bossRange) { if (LogInterval.Elapsed) { GlobalLog.Debug($"[KillBossTask] Going to {pos}"); } if (!pos.TryCome()) { GlobalLog.Error(MapData.Current.Type == MapType.Regular ? $"[KillBossTask] Unexpected error. Fail to move to map boss ({pos.Name}) in a regular map." : $"[KillBossTask] Fail to move to the map boss \"{pos.Name}\". Will try again after area transition."); _currentTarget.Unwalkable = true; _currentTarget = null; } return(true); } var attempts = ++_currentTarget.InteractionAttempts; // Helps to trigger Gorge and Underground River bosses if (attempts == MaxKillAttempts / 4) { GlobalLog.Debug("[KillBossTask] Trying to move around to trigger a boss."); var distantPos = WorldPosition.FindPathablePositionAtDistance(40, 70, 5); if (distantPos != null) { await Move.AtOnce(distantPos, "distant position", 10); } } if (attempts > MaxKillAttempts) { GlobalLog.Error("[KillBossTask] Boss did not become active. Now ignoring it."); _currentTarget.Ignored = true; _currentTarget = null; RegisterDeath(); return(true); } await Coroutines.FinishCurrentAction(); GlobalLog.Debug($"[KillBossTask] Waiting for map boss to become active ({attempts}/{MaxKillAttempts})"); await Wait.StuckDetectionSleep(200); return(true); }
public void Tick() { if (BossKilled || MapExplorationTask.MapCompleted) { return; } if (!TickInterval.Elapsed) { return; } if (!LokiPoe.IsInGame || !World.CurrentArea.IsMap) { return; } foreach (var obj in LokiPoe.ObjectManager.Objects) { var mob = obj as Monster; if (mob == null || !_isMapBoss(mob)) { continue; } var id = mob.Id; var cached = CachedBosses.Find(b => b.Id == id); if (!mob.IsDead) { var pos = mob.WalkablePosition(5, 20); if (cached != null) { cached.Position = pos; } else { CachedBosses.Add(new CachedBoss(id, pos, false)); GlobalLog.Warn($"[KillBossTask] Registering {pos}"); } } else { if (cached == null) { GlobalLog.Warn($"[KillBossTask] Registering dead map boss \"{mob.Name}\"."); CachedBosses.Add(new CachedBoss(id, mob.WalkablePosition(), true)); RegisterDeath(); } else if (!cached.IsDead) { GlobalLog.Warn($"[KillBossTask] Registering death of \"{mob.Name}\"."); cached.IsDead = true; if (!_multiPhaseBoss) { _currentTarget = null; } RegisterDeath(); } } } }