예제 #1
0
        public void ProcessState()
        {
            // Nothing to salvage in stations
            if (Cache.Instance.InStation)
            {
                return;
            }

            var cargo = Cache.Instance.DirectEve.GetShipsCargo();

            switch (State)
            {
            case SalvageState.TargetWrecks:
                TargetWrecks();

                // Next state
                State = SalvageState.LootWrecks;
                break;

            case SalvageState.LootWrecks:
                LootWrecks();

                State = SalvageState.SalvageWrecks;
                break;

            case SalvageState.SalvageWrecks:
                ActivateTractorBeams();
                ActivateSalvagers();

                // Default action
                State = SalvageState.TargetWrecks;
                if (cargo.IsReady && cargo.Items.Any() && _nextAction < DateTime.Now)
                {
                    // Check if there are actually duplicates
                    var duplicates = cargo.Items.Where(i => i.Quantity > 0).GroupBy(i => i.TypeId).Any(t => t.Count() > 1);
                    if (duplicates)
                    {
                        State = SalvageState.StackItems;
                    }
                    else
                    {
                        _nextAction = DateTime.Now.AddSeconds(150);
                    }
                }
                break;

            case SalvageState.StackItems:
                Logging.Log("Salvage: Stacking items");

                if (cargo.IsReady)
                {
                    cargo.StackAll();
                }

                _nextAction = DateTime.Now.AddSeconds(5);
                State       = SalvageState.WaitForStacking;
                break;

            case SalvageState.WaitForStacking:
                // Wait 5 seconds after stacking
                if (_nextAction > DateTime.Now)
                {
                    break;
                }

                if (Cache.Instance.DirectEve.GetLockedItems().Count == 0)
                {
                    Logging.Log("Salvage: Done stacking");
                    State = SalvageState.TargetWrecks;
                    break;
                }

                if (DateTime.Now.Subtract(_nextAction).TotalSeconds > 120)
                {
                    Logging.Log("Salvage: Stacking items timed out, clearing item locks");
                    Cache.Instance.DirectEve.UnlockItems();

                    Logging.Log("Salvage: Done stacking");
                    State = SalvageState.TargetWrecks;
                    break;
                }
                break;

            default:
                // Unknown state, goto first state
                State = SalvageState.TargetWrecks;
                break;
            }
        }
예제 #2
0
        /// <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 > 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;
            }
        }
예제 #3
0
파일: Drones.cs 프로젝트: ahaw/Questor
        public void ProcessState()
        {
            if (!Settings.Instance.UseDrones)
            {
                return;
            }

            switch (State)
            {
            case DroneState.WaitingForTargets:
                // Are we in the right state ?
                if (Cache.Instance.ActiveDrones.Count() > 0)
                {
                    // Apparently not, we have drones out, go into fight mode
                    State = DroneState.Fighting;
                    break;
                }

                // Should we launch drones?
                var launch = true;
                // Always launch if we're scrambled
                if (!Cache.Instance.PriorityTargets.Any(pt => pt.IsWarpScramblingMe))
                {
                    launch &= Cache.Instance.UseDrones;
                    // Are we done with this mission pocket?
                    launch &= !Cache.Instance.IsMissionPocketDone;

                    // If above minimums
                    launch &= Cache.Instance.DirectEve.ActiveShip.ShieldPercentage >= Settings.Instance.DroneMinimumShieldPct;
                    launch &= Cache.Instance.DirectEve.ActiveShip.ArmorPercentage >= Settings.Instance.DroneMinimumArmorPct;
                    launch &= Cache.Instance.DirectEve.ActiveShip.CapacitorPercentage >= Settings.Instance.DroneMinimumCapacitorPct;

                    // yes if there are targets to kill
                    launch &= Cache.Instance.TargetedBy.Count(e => !e.IsSentry && e.CategoryId == (int)CategoryID.Entity && e.IsNpc && !e.IsContainer && e.GroupId != (int)Group.LargeCollidableStructure && e.Distance < Settings.Instance.DroneControlRange) > 0;

                    // If drones get agro'd within 30 seconds, then wait (5 * _recallCount + 5) seconds since the last recall
                    if (_lastLaunch < _lastRecall && _lastRecall.Subtract(_lastLaunch).TotalSeconds < 30)
                    {
                        if (_lastRecall.AddSeconds(5 * _recallCount + 5) < DateTime.Now)
                        {
                            // Increase recall count and allow the launch
                            _recallCount++;

                            // Never let _recallCount go above 5
                            if (_recallCount > 5)
                            {
                                _recallCount = 5;
                            }
                        }
                        else
                        {
                            // Do not launch the drones until the delay has passed
                            launch = false;
                        }
                    }
                    else     // Drones have been out for more then 30s
                    {
                        _recallCount = 0;
                    }
                }

                if (launch)
                {
                    // Reset launch tries
                    _launchTries = 0;
                    _lastLaunch  = DateTime.Now;
                    State        = DroneState.Launch;
                }
                break;

            case DroneState.Launch:
                // Launch all drones
                _launchTimeout = DateTime.Now;
                Cache.Instance.DirectEve.ActiveShip.LaunchAllDrones();
                State = DroneState.Launching;
                break;

            case DroneState.Launching:
                // We haven't launched anything yet, keep waiting
                if (Cache.Instance.ActiveDrones.Count() == 0)
                {
                    if (DateTime.Now.Subtract(_launchTimeout).TotalSeconds > 10)
                    {
                        // Relaunch if tries < 10
                        if (_launchTries < 10)
                        {
                            _launchTries++;
                            State = DroneState.Launch;
                            break;
                        }
                        else
                        {
                            State = DroneState.OutOfDrones;
                        }
                    }
                    break;
                }

                // Are we done launching?
                if (_lastDroneCount == Cache.Instance.ActiveDrones.Count())
                {
                    State = DroneState.Fighting;
                }
                break;

            case DroneState.OutOfDrones:
                //if (DateTime.Now.Subtract(_launchTimeout).TotalSeconds > 1000)
                //{
                //    State = DroneState.WaitingForTargets;
                //}
                break;

            case DroneState.Fighting:
                // Should we recall our drones? This is a possible list of reasons why we should
                var recall = false;

                // Are we done (for now) ?
                if (Cache.Instance.TargetedBy.Count(e => !e.IsSentry && e.IsNpc && e.Distance < Settings.Instance.DroneControlRange) == 0)
                {
                    Logging.Log("Drones: Recalling drones because no NPC is targeting us within dronerange");
                    recall = true;
                }

                if (Cache.Instance.IsMissionPocketDone)
                {
                    Logging.Log("Drones: Recalling drones because we are done with this pocket.");
                    recall = true;
                }
                else if (_shieldPctTotal > GetShieldPctTotal())
                {
                    Logging.Log("Drones: Recalling drones because we have lost shields! [Old: " + _shieldPctTotal.ToString("N2") + "][New: " + GetShieldPctTotal().ToString("N2") + "]");
                    recall = true;
                }
                else if (_armorPctTotal > GetArmorPctTotal())
                {
                    Logging.Log("Drones: Recalling drones because we have lost armor! [Old:" + _armorPctTotal.ToString("N2") + "][New: " + GetArmorPctTotal().ToString("N2") + "]");
                    recall = true;
                }
                else if (_structurePctTotal > GetStructurePctTotal())
                {
                    Logging.Log("Drones: Recalling drones because we have lost structure! [Old:" + _structurePctTotal.ToString("N2") + "][New: " + GetStructurePctTotal().ToString("N2") + "]");
                    recall = true;
                }
                else if (Cache.Instance.ActiveDrones.Count() < _lastDroneCount)
                {
                    // Did we lose a drone? (this should be covered by total's as well though)
                    Logging.Log("Drones: Recalling drones because we have lost a drone! [Old:" + _lastDroneCount + "][New: " + Cache.Instance.ActiveDrones.Count() + "]");
                    recall = true;
                }
                else
                {
                    // Default to long range recall
                    var lowShieldWarning = Settings.Instance.LongRangeDroneRecallShieldPct;
                    var lowArmorWarning  = Settings.Instance.LongRangeDroneRecallArmorPct;
                    var lowCapWarning    = Settings.Instance.LongRangeDroneRecallCapacitorPct;

                    if (Cache.Instance.ActiveDrones.Average(d => d.Distance) < (Settings.Instance.DroneControlRange / 2d))
                    {
                        lowShieldWarning = Settings.Instance.DroneRecallShieldPct;
                        lowArmorWarning  = Settings.Instance.DroneRecallArmorPct;
                        lowCapWarning    = Settings.Instance.DroneRecallCapacitorPct;
                    }

                    if (Cache.Instance.DirectEve.ActiveShip.ShieldPercentage < lowShieldWarning)
                    {
                        Logging.Log("Drones: Recalling drones due to shield [" + Cache.Instance.DirectEve.ActiveShip.ShieldPercentage + "%] below [" + lowShieldWarning + "%] minimum");
                        recall = true;
                    }
                    else if (Cache.Instance.DirectEve.ActiveShip.ArmorPercentage < lowArmorWarning)
                    {
                        Logging.Log("Drones: Recalling drones due to armor [" + Cache.Instance.DirectEve.ActiveShip.ArmorPercentage + "%] below [" + lowArmorWarning + "%] minimum");
                        recall = true;
                    }
                    else if (Cache.Instance.DirectEve.ActiveShip.CapacitorPercentage < lowCapWarning)
                    {
                        Logging.Log("Drones: Recalling drones due to capacitor [" + Cache.Instance.DirectEve.ActiveShip.CapacitorPercentage + "%] below [" + lowCapWarning + "%] minimum");
                        recall = true;
                    }
                }

                if (Cache.Instance.ActiveDrones.Count() == 0)
                {
                    Logging.Log("Drones: Apparently we have lost all our drones");
                    recall = true;
                }
                else
                {
                    var isPanicking = false;
                    isPanicking |= Cache.Instance.DirectEve.ActiveShip.ShieldPercentage < Settings.Instance.MinimumShieldPct;
                    isPanicking |= Cache.Instance.DirectEve.ActiveShip.ArmorPercentage < Settings.Instance.MinimumArmorPct;
                    isPanicking |= Cache.Instance.DirectEve.ActiveShip.CapacitorPercentage < Settings.Instance.MinimumCapacitorPct;
                    if (Cache.Instance.PriorityTargets.Any(pt => pt.IsWarpScramblingMe) && recall)
                    {
                        Logging.Log("Drones: Overriding drone recall, we are scrambled!");
                        recall = false;
                    }
                }

                // Recall or engage
                if (recall)
                {
                    State = DroneState.Recalling;
                }
                else
                {
                    EngageTarget();

                    // We lost a drone and did not recall, assume panicking and launch (if any) additional drones
                    if (Cache.Instance.ActiveDrones.Count() < _lastDroneCount)
                    {
                        State = DroneState.Launch;
                    }
                }
                break;

            case DroneState.Recalling:
                // Are we done?
                if (Cache.Instance.ActiveDrones.Count() == 0)
                {
                    _lastRecall = DateTime.Now;
                    State       = DroneState.WaitingForTargets;
                    break;
                }

                // Give recall command every 5 seconds
                if (DateTime.Now.Subtract(_lastRecallCommand).TotalSeconds > 5)
                {
                    Cache.Instance.DirectEve.ExecuteCommand(DirectCmd.CmdDronesReturnToBay);
                    _lastRecallCommand = DateTime.Now;
                }
                break;
            }

            // Update health values
            _shieldPctTotal    = GetShieldPctTotal();
            _armorPctTotal     = GetArmorPctTotal();
            _structurePctTotal = GetStructurePctTotal();
            _lastDroneCount    = Cache.Instance.ActiveDrones.Count();
        }
예제 #4
0
        /// <summary>
        ///   Target wrecks within range
        /// </summary>
        private void TargetWrecks()
        {
            // We are jammed, we do not need to log (Combat does this already)
            if (Cache.Instance.DirectEve.ActiveShip.MaxLockedTargets == 0)
            {
                return;
            }

            var targets = new List <EntityCache>();

            targets.AddRange(Cache.Instance.Targets);
            targets.AddRange(Cache.Instance.Targeting);

            var hasSalvagers = Cache.Instance.Modules.Any(m => Salvagers.Contains(m.TypeId));
            var wreckTargets = targets.Where(t => (t.GroupId == (int)Group.Wreck || t.GroupId == (int)Group.CargoContainer) && t.CategoryId == (int)CategoryID.Celestial).ToList();

            // Check for cargo containers
            foreach (var wreck in wreckTargets)
            {
                if (Cache.Instance.IgnoreTargets.Contains(wreck.Name))
                {
                    Logging.Log("Salvage: Cargo Container [" + wreck.Name + "][" + wreck.Id + "] on the ignore list, ignoring.");
                    wreck.UnlockTarget();
                    continue;
                }

                if (hasSalvagers && wreck.GroupId != (int)Group.CargoContainer)
                {
                    continue;
                }

                // Unlock if within loot range
                if (wreck.Distance < 2500)
                {
                    Logging.Log("Salvage: Cargo Container [" + wreck.Name + "][" + wreck.Id + "] within loot range, unlocking container.");
                    wreck.UnlockTarget();
                }
            }

            if (wreckTargets.Count >= MaximumWreckTargets)
            {
                return;
            }

            var tractorBeams     = Cache.Instance.Modules.Where(m => TractorBeams.Contains(m.TypeId)).ToList();
            var tractorBeamRange = 0d;

            if (tractorBeams.Count > 0)
            {
                tractorBeamRange = tractorBeams.Min(t => t.OptimalRange);
            }

            var wrecks = Cache.Instance.UnlootedContainers;

            foreach (var wreck in wrecks.Where(w => !Cache.Instance.IgnoreTargets.Contains(w.Name.Trim())))
            {
                // Its already a target, ignore it
                if (wreck.IsTarget || wreck.IsTargeting)
                {
                    continue;
                }

                if (wreck.Distance > tractorBeamRange)
                {
                    continue;
                }

                if (!wreck.HaveLootRights)
                {
                    continue;
                }

                // No need to tractor a non-wreck within loot range
                if (wreck.GroupId != (int)Group.Wreck && wreck.Distance < 2500)
                {
                    continue;
                }

                if (wreck.GroupId != (int)Group.Wreck && wreck.GroupId != (int)Group.CargoContainer)
                {
                    continue;
                }

                if (!hasSalvagers)
                {
                    // Ignore already looted wreck
                    if (Cache.Instance.LootedContainers.Contains(wreck.Id))
                    {
                        continue;
                    }

                    // Ignore empty wrecks
                    if (wreck.GroupId == (int)Group.Wreck && wreck.IsWreckEmpty)
                    {
                        continue;
                    }
                }

                Logging.Log("Salvage: Locking [" + wreck.Name + "][" + wreck.Id + "]");

                wreck.LockTarget();
                wreckTargets.Add(wreck);

                if (wreckTargets.Count >= MaximumWreckTargets)
                {
                    break;
                }
            }
        }
예제 #5
0
        /// <summary>
        ///   Navigate to a solar system
        /// </summary>
        /// <param name = "solarSystemId"></param>
        private void NagivateToBookmarkSystem(long solarSystemId)
        {
            if (_nextTravelerAction > DateTime.Now)
            {
                return;
            }

            var undockBookmark = UndockBookmark;

            UndockBookmark = undockBookmark;

            var destination = Cache.Instance.DirectEve.Navigation.GetDestinationPath();

            if (destination.Count == 0 || !destination.Any(d => d == solarSystemId))
            {
                // We do not have the destination set
                var location = Cache.Instance.DirectEve.Navigation.GetLocation(solarSystemId);
                if (location.IsValid)
                {
                    Logging.Log("Traveler: Setting destination to [" + location.Name + "]");
                    location.SetDestination();
                }
                else
                {
                    Logging.Log("Traveler: Error setting solar system destination [" + solarSystemId + "]");
                    State = TravelerState.Error;
                }

                return;
            }
            else
            {
                if (!Cache.Instance.InSpace)
                {
                    if (Cache.Instance.InStation)
                    {
                        Cache.Instance.DirectEve.ExecuteCommand(DirectCmd.CmdExitStation);
                        _nextTravelerAction = DateTime.Now.AddSeconds((int)Time.TravelerExitStationAmIInSpaceYet_seconds);
                    }

                    // We are not yet in space, wait for it
                    return;
                }

                // Find the first waypoint
                var waypoint = destination.First();

                // Get the name of the next systems
                var locationName = Cache.Instance.DirectEve.Navigation.GetLocationName(waypoint);

                // Find the stargate associated with it
                var entities = Cache.Instance.EntitiesByName(locationName).Where(e => e.GroupId == (int)Group.Stargate);
                if (entities.Count() == 0)
                {
                    // not found, that cant be true?!?!?!?!
                    Logging.Log("Traveler: Error [Stargate (" + locationName + ")] not found, most likely lag waiting 15 seconds.");
                    _nextTravelerAction = DateTime.Now.AddSeconds((int)Time.TravelerNoStargatesFoundRetryDelay_seconds);
                    return;
                }

                // Warp to, approach or jump the stargate
                var entity = entities.First();
                if (entity.Distance < (int)Distance.DecloakRange)
                {
                    Logging.Log("Traveler: Jumping to [" + locationName + "]");
                    entity.Jump();

                    _nextTravelerAction = DateTime.Now.AddSeconds((int)Time.TravelerJumpedGateNextCommandDelay_seconds);
                }
                else if (entity.Distance < (int)Distance.WarptoDistance)
                {
                    entity.Approach(); //you could use a negative approach distance here but ultimately that is a bad idea.. Id like to go toward the entity without approaching it so we would end up inside the docking ring (eventually)
                }
                else
                {
                    Logging.Log("Traveler: Warping to [Stargate (" + locationName + ")]");
                    entity.WarpTo();
                    _nextTravelerAction = DateTime.Now.AddSeconds((int)Time.TravelerInWarpedNextCommandDelay_seconds);
                }
            }
        }