/// <summary> /// Loot any wrecks & cargo containers close by /// </summary> private void LootWrecks() { var cargo = Cache.Instance.DirectEve.GetShipsCargo(); if (cargo.Window == null) { // No, command it to open Cache.Instance.DirectEve.ExecuteCommand(DirectCmd.OpenCargoHoldOfActiveShip); return; } // Ship's cargo is not ready yet if (!cargo.IsReady) { return; } var shipsCargo = cargo.Items.Select(i => new ItemCache(i)).ToList(); var freeCargoCapacity = cargo.Capacity - cargo.UsedCapacity; var lootWindows = Cache.Instance.DirectEve.Windows.OfType <DirectContainerWindow>().Where(w => !string.IsNullOrEmpty(w.Name) && w.Name.StartsWith("loot_")); foreach (var window in lootWindows) { // The window is not ready, then continue if (!window.IsReady) { continue; } // Get the container var containerEntity = Cache.Instance.EntityById(window.ItemId); // Does it no longer exist or is it out of transfer range or its looted if (containerEntity == null || containerEntity.Distance > 2500 || Cache.Instance.LootedContainers.Contains(containerEntity.Id)) { Logging.Log("Salvage: Closing loot window [" + window.ItemId + "]"); window.Close(); continue; } // Get the container that is associated with the cargo container var container = Cache.Instance.DirectEve.GetContainer(window.ItemId); // List its items var items = container.Items.Select(i => new ItemCache(i)); // Build a list of items to loot var lootItems = new List <ItemCache>(); // Walk through the list of items ordered by highest value item first foreach (var item in items.OrderByDescending(i => i.IskPerM3)) { // We pick up loot depending on isk per m3 var isMissionItem = Cache.Instance.MissionItems.Contains((item.Name ?? string.Empty).ToLower()); // Never pick up contraband (unless its the mission item) if (!isMissionItem && item.IsContraband) { continue; } // Do we want to loot other items? if (!isMissionItem && !LootEverything) { continue; } // We are at our max, either make room or skip the item if ((freeCargoCapacity - item.TotalVolume) <= (isMissionItem ? 0 : ReserveCargoCapacity)) { // We can't drop items in this container anyway, well get it after its salvaged if (!isMissionItem && containerEntity.GroupId != (int)Group.CargoContainer) { continue; } // Make a list of items which are worth less List <ItemCache> worthLess; if (isMissionItem) { worthLess = shipsCargo; } else if (item.IskPerM3.HasValue) { worthLess = shipsCargo.Where(sc => sc.IskPerM3.HasValue && sc.IskPerM3 < item.IskPerM3).ToList(); } else { worthLess = shipsCargo.Where(sc => sc.IskPerM3.HasValue).ToList(); } // Remove mission item from this list worthLess.RemoveAll(wl => Cache.Instance.MissionItems.Contains((wl.Name ?? string.Empty).ToLower())); worthLess.RemoveAll(wl => (wl.Name ?? string.Empty).ToLower() == Cache.Instance.BringMissionItem); // Consider dropping ammo if it concerns the mission item! if (!isMissionItem) { worthLess.RemoveAll(wl => Ammo.Any(a => a.TypeId == wl.TypeId)); } // Nothing is worth less then the current item if (worthLess.Count() == 0) { continue; } // Not enough space even if we dumped the crap if ((freeCargoCapacity + worthLess.Sum(wl => wl.TotalVolume)) < item.TotalVolume) { if (isMissionItem) { Logging.Log("Salvage: Not enough space for mission item! Need [" + item.TotalVolume + "] maximum available [" + (freeCargoCapacity + worthLess.Sum(wl => wl.TotalVolume)) + "]"); } continue; } // Start clearing out items that are worth less var moveTheseItems = new List <DirectItem>(); foreach (var wl in worthLess.OrderBy(wl => wl.IskPerM3.HasValue ? wl.IskPerM3.Value : double.MaxValue).ThenByDescending(wl => wl.TotalVolume)) { // Mark this item as moved moveTheseItems.Add(wl.DirectItem); // Substract (now) free volume freeCargoCapacity += wl.TotalVolume; // We freed up enough space? if ((freeCargoCapacity - item.TotalVolume) >= ReserveCargoCapacity) { break; } } if (moveTheseItems.Count > 0) { // If this is not a cargo container, then jettison loot if (containerEntity.GroupId != (int)Group.CargoContainer || isMissionItem) { if (DateTime.Now.Subtract(_lastJettison).TotalSeconds < 185) { return; } Logging.Log("Salvage: Jettisoning [" + moveTheseItems.Count + "] items to make room for the more valuable loot"); // Note: This could (in theory) f**k up with the bot jettison an item and // then picking it up again :/ (granted it should never happen unless // mission item volume > reserved volume cargo.Jettison(moveTheseItems.Select(i => i.ItemId)); _lastJettison = DateTime.Now; return; } // Move items to the cargo container container.Add(moveTheseItems); // Remove it from the ships cargo list shipsCargo.RemoveAll(i => moveTheseItems.Any(wl => wl.ItemId == i.Id)); Logging.Log("Salvage: Moving [" + moveTheseItems.Count + "] items into the cargo container to make room for the more valuable loot"); } } // Update free space freeCargoCapacity -= item.TotalVolume; lootItems.Add(item); } // Mark container as looted Cache.Instance.LootedContainers.Add(containerEntity.Id); // Loot actual items if (lootItems.Count != 0) { Logging.Log("Salvage: Looting container [" + containerEntity.Name + "][" + containerEntity.Id + "], [" + lootItems.Count + "] valuable items"); cargo.Add(lootItems.Select(i => i.DirectItem)); } else { Logging.Log("Salvage: Container [" + containerEntity.Name + "][" + containerEntity.Id + "] contained no valuable items"); } } // Open a container in range foreach (var containerEntity in Cache.Instance.Containers.Where(e => e.Distance <= 2500)) { // Emptry wreck, ignore if (containerEntity.GroupId == (int)Group.Wreck && containerEntity.IsWreckEmpty) { continue; } // We looted this container if (Cache.Instance.LootedContainers.Contains(containerEntity.Id)) { continue; } // We already opened the loot window var window = lootWindows.FirstOrDefault(w => w.ItemId == containerEntity.Id); if (window != null) { continue; } // Ignore open request within 10 seconds if (_openedContainers.ContainsKey(containerEntity.Id) && DateTime.Now.Subtract(_openedContainers[containerEntity.Id]).TotalSeconds < 10) { continue; } // Open the container Logging.Log("Salvage: Opening container [" + containerEntity.Name + "][" + containerEntity.Id + "]"); containerEntity.OpenCargo(); _openedContainers[containerEntity.Id] = DateTime.Now; break; } }
/// <summary> /// Loot any wrecks & cargo containers close by /// </summary> private void LootWrecks() { var cargo = Cache.Instance.DirectEve.GetShipsCargo(); if (cargo.Window == null) { // No, command it to open Cache.Instance.DirectEve.ExecuteCommand(DirectCmd.OpenCargoHoldOfActiveShip); return; } // Ship's cargo is not ready yet if (!cargo.IsReady) { return; } var shipsCargo = cargo.Items.Select(i => new ItemCache(i)).ToList(); var freeCargoCapacity = cargo.Capacity - cargo.UsedCapacity; var lootWindows = Cache.Instance.DirectEve.Windows.OfType <DirectContainerWindow>().Where(w => w.Type == "form.LootCargoView"); foreach (var window in lootWindows) { // The window is not ready, then continue if (!window.IsReady) { continue; } // Get the container var containerEntity = Cache.Instance.EntityById(window.ItemId); // Does it no longer exist or is it out of transfer range or its looted if (containerEntity == null || containerEntity.Distance > (int)Distance.SafeScoopRange || Cache.Instance.LootedContainers.Contains(containerEntity.Id)) { Logging.Log("Salvage: Closing loot window [" + window.ItemId + "]"); window.Close(); continue; } // Get the container that is associated with the cargo container var container = Cache.Instance.DirectEve.GetContainer(window.ItemId); // List its items var items = container.Items.Select(i => new ItemCache(i)); // Build a list of items to loot var lootItems = new List <ItemCache>(); if (Settings.Instance.WreckLootStatistics) { // Log all items found in the wreck File.AppendAllText(Settings.Instance.WreckLootStatisticsFile, "TIME: " + string.Format("{0:dd/MM/yyyy HH:mm:ss}", DateTime.Now) + "\n"); File.AppendAllText(Settings.Instance.WreckLootStatisticsFile, "NAME: " + containerEntity.Name + "\n"); File.AppendAllText(Settings.Instance.WreckLootStatisticsFile, "ITEMS:" + "\n"); foreach (var item in items.OrderBy(i => i.TypeId)) { File.AppendAllText(Settings.Instance.WreckLootStatisticsFile, "TypeID: " + item.TypeId.ToString() + "\n"); File.AppendAllText(Settings.Instance.WreckLootStatisticsFile, "Name: " + item.Name + "\n"); File.AppendAllText(Settings.Instance.WreckLootStatisticsFile, "Quantity: " + item.Quantity.ToString() + "\n"); File.AppendAllText(Settings.Instance.WreckLootStatisticsFile, "=\n"); } File.AppendAllText(Settings.Instance.WreckLootStatisticsFile, ";" + "\n"); } //if (freeCargoCapacity < 1000) //this should allow BSs to dump scrapmetal but haulers and noctus' to hold onto it //{ // // Dump scrap metal if we have any // if (containerEntity.Name == "Cargo Container" && shipsCargo.Any(i => i.IsScrapMetal)) // { // foreach (var item in shipsCargo.Where(i => i.IsScrapMetal)) // { // container.Add(item.DirectItem); // freeCargoCapacity += item.TotalVolume; // } // // shipsCargo.RemoveAll(i => i.IsScrapMetal); // } //} // Walk through the list of items ordered by highest value item first foreach (var item in items.OrderByDescending(i => i.IskPerM3)) { if (freeCargoCapacity < 1000) //this should allow BSs to not pickup large low value items but haulers and noctus' to scoop everything { // We never want to pick up a cap booster if (item.GroupID == (int)Group.CapacitorGroupCharge) { continue; } // We never want to pick up metal scraps //if (item.IsScrapMetal) // continue; } // We pick up loot depending on isk per m3 var isMissionItem = Cache.Instance.MissionItems.Contains((item.Name ?? string.Empty).ToLower()); // Never pick up contraband (unless its the mission item) if (!isMissionItem && item.IsContraband) { continue; } // Do we want to loot other items? if (!isMissionItem && !LootEverything) { continue; } // Do not pick up items that cannot enter in a freighter container (unless its the mission item) // Note: some mission items that are alive have been allowed to be // scooped because unloadlootstate.MoveCommonMissionCompletionitems // will move them into the hangar floor not the loot location if (!isMissionItem && item.IsAliveandWontFitInContainers) { continue; } // We are at our max, either make room or skip the item if ((freeCargoCapacity - item.TotalVolume) <= (isMissionItem ? 0 : ReserveCargoCapacity)) { // We can't drop items in this container anyway, well get it after its salvaged if (!isMissionItem && containerEntity.GroupId != (int)Group.CargoContainer) { continue; } // Make a list of items which are worth less List <ItemCache> worthLess; if (isMissionItem) { worthLess = shipsCargo; } else if (item.IskPerM3.HasValue) { worthLess = shipsCargo.Where(sc => sc.IskPerM3.HasValue && sc.IskPerM3 < item.IskPerM3).ToList(); } else { worthLess = shipsCargo.Where(sc => sc.IskPerM3.HasValue).ToList(); } // Remove mission item from this list worthLess.RemoveAll(wl => Cache.Instance.MissionItems.Contains((wl.Name ?? string.Empty).ToLower())); worthLess.RemoveAll(wl => (wl.Name ?? string.Empty).ToLower() == Cache.Instance.BringMissionItem); // Consider dropping ammo if it concerns the mission item! if (!isMissionItem) { worthLess.RemoveAll(wl => Ammo.Any(a => a.TypeId == wl.TypeId)); } // Nothing is worth less then the current item if (worthLess.Count() == 0) { continue; } // Not enough space even if we dumped the crap if ((freeCargoCapacity + worthLess.Sum(wl => wl.TotalVolume)) < item.TotalVolume) { if (isMissionItem) { Logging.Log("Salvage: Not enough space for mission item! Need [" + item.TotalVolume + "] maximum available [" + (freeCargoCapacity + worthLess.Sum(wl => wl.TotalVolume)) + "]"); } continue; } // Start clearing out items that are worth less var moveTheseItems = new List <DirectItem>(); foreach (var wl in worthLess.OrderBy(wl => wl.IskPerM3.HasValue ? wl.IskPerM3.Value : double.MaxValue).ThenByDescending(wl => wl.TotalVolume)) { // Mark this item as moved moveTheseItems.Add(wl.DirectItem); // Subtract (now) free volume freeCargoCapacity += wl.TotalVolume; // We freed up enough space? if ((freeCargoCapacity - item.TotalVolume) >= ReserveCargoCapacity) { break; } } if (moveTheseItems.Count > 0) { // If this is not a cargo container, then jettison loot if (containerEntity.GroupId != (int)Group.CargoContainer || isMissionItem) { if (DateTime.Now.Subtract(_lastJettison).TotalSeconds < (int)Time.DelayBetweenJetcans_seconds) { return; } Logging.Log("Salvage: Jettisoning [" + moveTheseItems.Count + "] items to make room for the more valuable loot"); // Note: This could (in theory) f**k up with the bot jettison an item and // then picking it up again :/ (granted it should never happen unless // mission item volume > reserved volume cargo.Jettison(moveTheseItems.Select(i => i.ItemId)); _lastJettison = DateTime.Now; return; } // Move items to the cargo container container.Add(moveTheseItems); // Remove it from the ships cargo list shipsCargo.RemoveAll(i => moveTheseItems.Any(wl => wl.ItemId == i.Id)); Logging.Log("Salvage: Moving [" + moveTheseItems.Count + "] items into the cargo container to make room for the more valuable loot"); } } // Update free space freeCargoCapacity -= item.TotalVolume; lootItems.Add(item); } // Mark container as looted Cache.Instance.LootedContainers.Add(containerEntity.Id); // Loot actual items if (lootItems.Count != 0) { Logging.Log("Salvage: Looting container [" + containerEntity.Name + "][ID: " + containerEntity.Id + "], [" + lootItems.Count + "] valuable items"); cargo.Add(lootItems.Select(i => i.DirectItem)); } else { Logging.Log("Salvage: Container [" + containerEntity.Name + "][ID: " + containerEntity.Id + "] contained no valuable items"); } } // Open a container in range foreach (var containerEntity in Cache.Instance.Containers.Where(e => e.Distance <= (int)Distance.SafeScoopRange)) { // Emptry wreck, ignore if (containerEntity.GroupId == (int)Group.Wreck && containerEntity.IsWreckEmpty) { continue; } // We looted this container if (Cache.Instance.LootedContainers.Contains(containerEntity.Id)) { continue; } // We already opened the loot window var window = lootWindows.FirstOrDefault(w => w.ItemId == containerEntity.Id); if (window != null) { continue; } // Ignore open request within 10 seconds if (_openedContainers.ContainsKey(containerEntity.Id) && DateTime.Now.Subtract(_openedContainers[containerEntity.Id]).TotalSeconds < 10) { continue; } // Don't even try to open a wreck if you are speed tanking and you aren't processing a loot action if (Settings.Instance.SpeedTank == true && Cache.Instance.OpenWrecks == false) { continue; } // Don't even try to open a wreck if you are specified LootEverything as false and you aren't processing a loot action // this is currently commented out as it would keep golems and other non-speed tanked ships from looting the field as they cleared // missions, but NOT stick around after killing things to clear it ALL. Looteverything==false does NOT mean loot nothing //if (Settings.Instance.LootEverything == false && Cache.Instance.OpenWrecks == false) // continue; // Open the container Logging.Log("Salvage: Opening container [" + containerEntity.Name + "][ID: " + containerEntity.Id + "]"); containerEntity.OpenCargo(); _openedContainers[containerEntity.Id] = DateTime.Now; break; } }