public ISerializableBotTask GetNextTankingModulesTask(double estimatedIncomingDps) { DynamicTask task = new DynamicTask(); var shieldBoosters = Fit.GetShieldBoostersModules().ToList(); if (HitpointsAndEnergy.Shield < 600) { if (estimatedIncomingDps <= 150) { task.With($"Incoming DPS is {estimatedIncomingDps}. Turning on single SB"); return(shieldBoosters.FirstOrDefault().EnsureActive(bot, true) ?? shieldBoosters.Skip(1).Select(sb => sb.EnsureActive(bot, false)) .FirstOrDefault(t => t != null)); } else { return(shieldBoosters.Select(sb => sb.EnsureActive(bot, true)) .FirstOrDefault(t => t != null)); } } else { if (HitpointsAndEnergy.Shield > 800 || HitpointsAndEnergy.Capacitor < 400) { task.With("Shield HP OK, energy low, turning off SB."); foreach (var sb in shieldBoosters) { var t = sb.EnsureActive(bot, false); if (t != null) { return(t); } } } } return(null); }
public ISerializableBotTask GetActions([NotNull] ShipState shipState, [NotNull] MemoryProxyOverviewProvider overviewProvider, [NotNull] MemoryProxyInventoryProvider inventoryProvider) { stepIndex++; var task = new DynamicTask(); if (!shipState.ManeuverStartPossible) { return(null); } if (LeavingAbyssTimestamp.HasValue && LeavingAbyssTimestamp.Value.Add(TimeSpan.FromMinutes(1.2)) > StateStopwatch.Elapsed) { return(task.With( $"Left abyss. Waiting {LeavingAbyssTimestamp.Value.Add(TimeSpan.FromMinutes(1.2)) - StateStopwatch.Elapsed} to leave invulnerability")); } if (!shipState.IsInAbyss) { if (enteredAbyss) { LeavingAbyssTimestamp = StateStopwatch.Elapsed; enteredAbyss = false; //TODO check need for refill; return(task.With("Left abyss. Waiting a minute to leave invulnerability")); } var enterAbyssTask = EnterAbyssIfNeeded(shipState, inventoryProvider); if (enterAbyssTask != null) { return(enterAbyssTask); } } else { enteringAbyss = false; enteredAbyss = true; } var turnOnAlwaysActiveModulesTask = shipState.GetTurnOnAlwaysActiveModulesTask(); if (turnOnAlwaysActiveModulesTask != null) { return(task.With(turnOnAlwaysActiveModulesTask)); } var overviewEntries = overviewProvider.Entries; var offensiveOverviewEntries = overviewEntries ?.Where(entry => entry.IsEnemy) ?.Where(entry => !entry.Name.Contains("Extraction")) ?.Where(e => e.Type != "Vila Swarmer") ?.ToList(); var listOverviewEntryToAttack = offensiveOverviewEntries ?.Where(entry => entry.Distance <= maxTargetDistance) ?.Where(entry => entry.Name != "Vila Swarmer") ?.OrderBy(CalcTargetPriority) ?.ThenBy(entry => entry?.Distance ?? int.MaxValue) ?.ToArray(); var estimatedIncomingDps = CalculateApproximateDps(offensiveOverviewEntries); var conduit = overviewEntries ?.Where(entry => entry.Name.Contains("Conduit") && !entry.Name.Contains("Proving")) ?.SingleOrDefault(); var orbitBeacon = overviewEntries?.Where(IsOrbitBeacon)?.OrderBy(CalcTargetPriority)?.FirstOrDefault() ?? conduit; task.With($"Current maneuver is {shipState.Maneuver}." + Environment.NewLine + $"Incoming DPS is {estimatedIncomingDps}."); //goto targetProcessing; if (estimatedIncomingDps > 200) { if (shipState.Maneuver != ShipManeuverTypeEnum.Orbit) { task.With($"Orbiting {conduit}"); return(task.With(orbitBeacon.ClickMenuEntryByRegexPattern("Orbit.*", "5,000 m"))); } var mwdTask = shipState.GetSetModuleActiveTask(ShipFit.ModuleType.MWD, shipState.HitpointsAndEnergy.Capacitor > 200); if (mwdTask != null && MwdLastTurnOnAttempt < stepIndex - 10) { MwdLastTurnOnAttempt = stepIndex; return(task.With(mwdTask)); } } else { task.With($"Incoming DPS is {estimatedIncomingDps}. No need to avoid"); if (shipState.Maneuver != ShipManeuverTypeEnum.Approach && shipState.Maneuver != ShipManeuverTypeEnum.KeepAtRange) { return(task.With(conduit.ClickMenuEntryByRegexPattern("Keep at range", "500 m"))); } task.With($"Distance to target is {conduit.Distance}."); var mwdTask = shipState.GetSetModuleActiveTask(ShipFit.ModuleType.MWD, conduit.Distance > 5000); if (mwdTask != null) { return(task.With(mwdTask)); } } var tankingTask = shipState.GetNextTankingModulesTask(estimatedIncomingDps); if (tankingTask != null) { return(task.With(tankingTask)); } targetProcessing: #region drones var drones = shipState.Drones; #endregion //task.With($"Weapon status: IsActive = {weaponGroup.UiModule.IsActive(bot)}. IsReloading = {weaponGroup.UiModule.IsReloading(bot)}. Ramp = {weaponGroup.UiModule.RampRotationMilli}"); if (shipState.ActiveTargets.Count > 0) { task.With($"Targets selected: {shipState.ActiveTargets.Count}"); var focusedTarget = shipState.ActiveTargets.List.Last(); ISerializableBotTask weaponTask = shipState.GetSetModuleActiveTask(ShipFit.ModuleType.Weapon, focusedTarget.Distance < 25000); if (weaponTask != null) { return(task.With(weaponTask)); } var shouldDronesAttack = !focusedTarget.DroneAssigned && focusedTarget.Distance <= 55000; if (shouldDronesAttack) { task.With($"No target attacked. Launching drones."); if (drones.ShouldLaunch) { return(task.With(HotkeyRegistry.LaunchDrones)); } return(task.With(HotkeyRegistry.EngageDrones)); } } task.With( $"Spare enemies to attack: {listOverviewEntryToAttack.Length}: {string.Concat(listOverviewEntryToAttack.Select(oe => Environment.NewLine + '\t' + (oe.MeTargeted == true ? "[Targeted]" : string.Empty) + oe.Name))}"); if (shipState.ActiveTargets == null || shipState.ActiveTargets.Count < 5) { foreach (var overviewEntry in listOverviewEntryToAttack.Where(e => e.MeTargeted != true)) { if (lastTargetingAttemptSteps.ContainsKey(overviewEntry.Id)) { if (lastTargetingAttemptSteps[overviewEntry.Id] > stepIndex - 3) { continue; } } lastTargetingAttemptSteps[overviewEntry.Id] = stepIndex; return(task.With(overviewEntry.GetSelectTask())); } } var wrongTargetedEntries = shipState.ActiveTargets?.List?.Where(t => ((!t.Name.Contains("Extraction") && !offensiveOverviewEntries.Any(oe => oe.Name == t.Name)) || (t.Name.Contains("Extraction") && t.Distance > 50000))); if (wrongTargetedEntries?.Any() ?? false) { task.With( $"Wrong targeted entries: {string.Join(",", wrongTargetedEntries.Select(wte => wte.Name + "@" + wte.Distance + "[" + offensiveOverviewEntries.Any(oe => oe.Name == wte.Name) + "]"))}"); return(task.With(wrongTargetedEntries.FirstOrDefault().GetUnlockTask())); } if (!(0 < listOverviewEntryToAttack?.Length)) { var reloadTask = shipState.GetReloadTask(); if (drones.HasNonReturningDronesInSpace) { return(task.With(HotkeyRegistry.ReturnDrones)); } else if (reloadTask != null) { return(task.With(reloadTask)); } } looting: if (overviewEntries.Any(e => e.Name.Contains("Bioadaptive"))) { if (conduit.Distance < 2000 && !overviewEntries.Any(e => e.Name.Contains("Tractor"))) { var openInventoryTask = inventoryProvider.GetOpenWindowTask(); if (openInventoryTask != null) { return(task.With(openInventoryTask)); } task.With("We are near conduit and have nothing to do. Time to deploy tractor"); var launchTractorTask = inventoryProvider.GetActvateItemIfPresentTask("Mobile Tractor Unit", ".*Launch.*"); if (launchTractorTask != null) { return(task.With(launchTractorTask)); } } } else if (overviewEntries.Any(e => e.Name.Contains("Tractor"))) { var tractorEntry = overviewEntries.Single(e => e.Name.Contains("Tractor")); var lootWindowProvider = inventoryProvider.GetLootableWindow(); if (lootWindowProvider != null) { return(task.With( lootWindowProvider.IsEmpty ? tractorEntry.ClickMenuEntryByRegexPattern("Scoop.*") : lootWindowProvider.GetClickLootButtonTask())); } if (tractorEntry.Distance < 2500) { return(task.With(tractorEntry.ClickMenuEntryByRegexPattern("Open Cargo"))); } if (shipState.Maneuver != ShipManeuverTypeEnum.Approach) { return(task.With("Approach")); } } else if (offensiveOverviewEntries.IsNullOrEmpty()) { var closeInventoryTask = inventoryProvider.GetCloseWindowTask(); if (closeInventoryTask != null) { return(task.With(closeInventoryTask)); } task.With("Room finished, time to jump"); return(task.With(conduit.ClickMenuEntryByRegexPattern("Activate Gate"))); } return(null); }