Beispiel #1
0
        public void ProcessState()
        {
            if (DateTime.UtcNow.Subtract(_lastPulse).TotalMilliseconds < Time.Instance.QuestorPulse_milliseconds) //default: 1500ms
            {
                return;
            }

            _lastPulse = DateTime.UtcNow;

            if (Cache.Instance.SessionState == "Quitting")
            {
                BeginClosingQuestor();
            }

            if (Cache.Instance.GotoBaseNow)
            {
                _States.CurrentMiningState = MiningState.GotoBase;
            }

            if ((DateTime.UtcNow.Subtract(Cache.Instance.QuestorStarted_DateTime).TotalSeconds > 10) &&
                (DateTime.UtcNow.Subtract(Cache.Instance.QuestorStarted_DateTime).TotalSeconds < 60))
            {
                if (Cache.Instance.QuestorJustStarted)
                {
                    Cache.Instance.QuestorJustStarted = false;
                    Cache.Instance.SessionState       = "Starting Up";

                    // write session log
                    Statistics.WriteSessionLogStarting();
                }
            }

            _panic.ProcessState();

            if (_States.CurrentPanicState == PanicState.Panic || _States.CurrentPanicState == PanicState.Panicking)
            {
                // If Panic is in panic state, questor is in panic States.CurrentCombatMissionBehaviorState :)
                _States.CurrentMiningState = MiningState.Panic;

                if (PanicStateReset)
                {
                    _States.CurrentPanicState = PanicState.Normal;
                    PanicStateReset           = false;
                }
            }
            else if (_States.CurrentPanicState == PanicState.Resume)
            {
                // Reset panic state
                _States.CurrentPanicState    = PanicState.Normal;
                _States.CurrentTravelerState = TravelerState.Idle;
                _States.CurrentMiningState   = MiningState.GotoBelt;
            }

            if (Settings.Instance.DebugMiningBehavior)
            {
                Logging.Log("MiningBehavior", "Pre-switch", Logging.White);
            }

            switch (_States.CurrentMiningState)
            {
            case MiningState.Default:
            case MiningState.Idle:
                _States.CurrentMiningState = MiningState.Cleanup;
                break;

            case MiningState.Cleanup:
                if (Cache.Instance.LootAlreadyUnloaded == false)
                {
                    _States.CurrentMiningState = MiningState.GotoBase;
                    break;
                }

                Cleanup.CheckEVEStatus();
                _States.CurrentMiningState = MiningState.Arm;
                break;

            case MiningState.GotoBase:
                DirectBookmark miningHome = Cache.Instance.BookmarksByLabel("Mining Home").FirstOrDefault();

                //Cache.Instance.DirectEve.Navigation.GetDestinationPath
                Traveler.TravelToMiningHomeBookmark(miningHome, "Mining go to base");

                if (_States.CurrentTravelerState == TravelerState.AtDestination)     // || DateTime.UtcNow.Subtract(Cache.Instance.EnteredCloseQuestor_DateTime).TotalMinutes > 10)
                {
                    if (Settings.Instance.DebugGotobase)
                    {
                        Logging.Log("MiningBehavior", "GotoBase: We are at destination", Logging.White);
                    }
                    Cache.Instance.GotoBaseNow = false;     //we are there - turn off the 'forced' gotobase
                    _States.CurrentMiningState = MiningState.UnloadLoot;
                    Traveler.Destination       = null;
                }
                break;

            case MiningState.UnloadLoot:

                //
                // this state should never be reached in space. if we are in space and in this state we should switch to gotobase
                //
                if (Cache.Instance.InSpace)
                {
                    Logging.Log(_States.CurrentCombatMissionBehaviorState.ToString(), "We are in space, how did we get set to this state while in space? Changing state to: GotoBase", Logging.White);
                    _States.CurrentMiningState = MiningState.GotoBase;
                }

                if (_States.CurrentUnloadLootState == UnloadLootState.Idle)
                {
                    Logging.Log("MiningBehavior", "UnloadLoot: Begin", Logging.White);
                    _States.CurrentUnloadLootState = UnloadLootState.Begin;
                }

                _unloadLoot.ProcessState();

                if (_States.CurrentUnloadLootState == UnloadLootState.Done)
                {
                    Cache.Instance.LootAlreadyUnloaded = true;
                    _States.CurrentUnloadLootState     = UnloadLootState.Idle;

                    if (_States.CurrentCombatState == CombatState.OutOfAmmo)
                    {
                        Logging.Log("MiningBehavior.UnloadLoot", "We are out of ammo", Logging.Orange);
                        _States.CurrentMiningState = MiningState.Idle;
                        return;
                    }

                    _States.CurrentMiningState  = MiningState.Idle;
                    _States.CurrentQuestorState = QuestorState.Idle;
                    Logging.Log("MiningBehavior.Unloadloot", "CharacterMode: [" + Settings.Instance.CharacterMode + "], AfterMissionSalvaging: [" + Settings.Instance.AfterMissionSalvaging + "], MiningState: [" + _States.CurrentMiningState + "]", Logging.White);
                    return;
                }
                break;

            case MiningState.Start:
                Cache.Instance.OpenWrecks  = false;
                _States.CurrentMiningState = MiningState.Arm;
                DirectBookmark asteroidShortcut = Cache.Instance.BookmarksByLabel("Asteroid Location").FirstOrDefault();

                if (asteroidShortcut != null)
                {
                    asteroidShortcut.Delete();
                }
                break;

            case MiningState.Arm:

                //
                // this state should never be reached in space. if we are in space and in this state we should switch to gotobase
                //
                if (Cache.Instance.InSpace)
                {
                    Logging.Log(_States.CurrentMiningState.ToString(), "We are in space, how did we get set to this state while in space? Changing state to: GotoBase", Logging.White);
                    _States.CurrentMiningState = MiningState.GotoBase;
                }

                if (_States.CurrentArmState == ArmState.Idle)
                {
                    Logging.Log("Arm", "Begin", Logging.White);
                    _States.CurrentArmState = ArmState.Begin;

                    // Load ammo... this "fixes" the problem I experienced with not reloading after second arm phase. The quantity was getting set to 0.
                    Arm.AmmoToLoad.Clear();
                    Arm.AmmoToLoad.Add(Settings.Instance.Ammo.FirstOrDefault());

                    //FIXME: bad hack - this should be fixed differently / elsewhere
                    Ammo FirstAmmoToLoad = Arm.AmmoToLoad.FirstOrDefault();
                    if (FirstAmmoToLoad != null && FirstAmmoToLoad.Quantity == 0)
                    {
                        FirstAmmoToLoad.Quantity = 333;
                    }
                }

                Arm.ProcessState();

                if (_States.CurrentArmState == ArmState.NotEnoughAmmo)
                {
                    // we know we are connected if we were able to arm the ship - update the lastknownGoodConnectedTime
                    // we may be out of drones/ammo but disconnecting/reconnecting will not fix that so update the timestamp
                    Cache.Instance.LastKnownGoodConnectedTime = DateTime.UtcNow;
                    Cache.Instance.MyWalletBalance            = Cache.Instance.DirectEve.Me.Wealth;
                    Logging.Log("Arm", "Armstate.NotEnoughAmmo", Logging.Orange);
                    _States.CurrentArmState    = ArmState.Idle;
                    _States.CurrentMiningState = MiningState.Error;
                }

                if (_States.CurrentArmState == ArmState.NotEnoughDrones)
                {
                    // we know we are connected if we were able to arm the ship - update the lastknownGoodConnectedTime
                    // we may be out of drones/ammo but disconnecting/reconnecting will not fix that so update the timestamp
                    Cache.Instance.LastKnownGoodConnectedTime = DateTime.UtcNow;
                    Cache.Instance.MyWalletBalance            = Cache.Instance.DirectEve.Me.Wealth;
                    Logging.Log("Arm", "Armstate.NotEnoughDrones", Logging.Orange);
                    _States.CurrentArmState    = ArmState.Idle;
                    _States.CurrentMiningState = MiningState.Error;
                }

                if (_States.CurrentArmState == ArmState.Done)
                {
                    if (DateTime.UtcNow > Cache.Instance.LastInSpace.AddSeconds(45))     //do not try to leave the station until you have been docked for at least 45seconds! (this gives some overhead to load the station env + session change timer)
                    {
                        //we know we are connected if we were able to arm the ship - update the lastknownGoodConnectedTime
                        Cache.Instance.LastKnownGoodConnectedTime = DateTime.UtcNow;
                        Cache.Instance.MyWalletBalance            = Cache.Instance.DirectEve.Me.Wealth;
                        _States.CurrentArmState   = ArmState.Idle;
                        _States.CurrentDroneState = DroneState.WaitingForTargets;


                        //exit the station
                        Cache.Instance.DirectEve.ExecuteCommand(DirectCmd.CmdExitStation);

                        //set up a wait of 10 seconds so the undock can complete
                        _lastPulse = DateTime.UtcNow.AddSeconds(10);
                        _States.CurrentMiningState = MiningState.GotoBelt;
                    }
                }
                break;

            case MiningState.GotoBelt:
                if (DateTime.UtcNow.Subtract(_lastPulse).TotalMilliseconds < Time.Instance.QuestorPulse_milliseconds * 2)
                {
                    return;
                }

                if (Cache.Instance.InWarp || (!Cache.Instance.InSpace && !Cache.Instance.InStation))
                {
                    return;
                }

                //
                // this should goto a mining system bookmark (one of possibly many)
                // then goto the 1st belt. This would allow for mining in systems without stations
                //
                Logging.Log("MiningBehavior", "Setting Destination to 1st Asteroid belt.", Logging.White);

                DirectBookmark asteroidShortcutGTB = Cache.Instance.BookmarksByLabel("Asteroid Location").FirstOrDefault();

                if (asteroidShortcutGTB != null)
                {
                    if (Cache.Instance.EntityById(_currentBelt.Id).Distance < 65000)
                    {
                        _States.CurrentMiningState = MiningState.Mine;
                        Traveler.Destination       = null;
                    }
                    else
                    {
                        asteroidShortcutGTB.WarpTo();
                        _lastPulse = DateTime.UtcNow;
                    }
                    break;
                }

                IEnumerable <EntityCache> belts = Cache.Instance.Entities.Where(i => i.GroupId == (int)Group.AsteroidBelt && !i.Name.ToLower().Contains("ice") && !EmptyBelts.Contains(i.Id));
                EntityCache belt = belts.OrderBy(x => x.Distance).FirstOrDefault();
                _currentBelt = belt;

                //Traveler.Destination = new MissionBookmarkDestination(belt);

                if (belt != null)
                {
                    if (belt.Distance < 35000)
                    {
                        _States.CurrentMiningState = MiningState.Mine;
                        Traveler.Destination       = null;
                    }
                    else
                    {
                        if (belt.WarpTo())
                        {
                            _lastPulse = DateTime.UtcNow;
                        }
                    }
                    break;
                }

                _States.CurrentMiningState = MiningState.GotoBase;
                Logging.Log("MiningBehavior", "Could not find a suitable Asteroid belt.", Logging.White);
                Settings.Instance.AutoStart = false;
                break;

            case MiningState.Mine:

                IEnumerable <EntityCache> _asteroidsOnGrid  = Cache.Instance.EntitiesOnGrid.Where(i => i.Distance < (int)Distances.OnGridWithMe && i.CategoryId == (int)CategoryID.Asteroid).OrderBy(i => i.Distance);
                IEnumerable <EntityCache> _asteroidsInRange = _asteroidsOnGrid.Where(i => i.Distance < 65000).ToList();
                EntityCache asteroid = null;

                if (asteroid == null && _asteroidsInRange.Any(i => i.GroupId == (int)Group.Kernite))
                {
                    asteroid = _asteroidsInRange.Where(i => i.GroupId == (int)Group.Kernite).OrderBy(i => i.Distance).FirstOrDefault();
                }

                if (asteroid == null && _asteroidsInRange.Any(i => i.GroupId == (int)Group.Plagioclase))
                {
                    asteroid = _asteroidsInRange.Where(i => i.GroupId == (int)Group.Plagioclase).OrderBy(i => i.Distance).FirstOrDefault();
                }

                if (asteroid == null && _asteroidsInRange.Any(i => i.GroupId == (int)Group.Pyroxeres))
                {
                    asteroid = _asteroidsInRange.Where(i => i.GroupId == (int)Group.Pyroxeres).OrderBy(i => i.Distance).FirstOrDefault();
                }

                if (asteroid == null && _asteroidsInRange.Any(i => i.GroupId == (int)Group.Scordite))
                {
                    asteroid = _asteroidsInRange.Where(i => i.GroupId == (int)Group.Scordite).OrderBy(i => i.Distance).FirstOrDefault();
                }

                if (asteroid == null && _asteroidsInRange.Any(i => i.GroupId == (int)Group.Veldspar))
                {
                    asteroid = _asteroidsInRange.Where(i => i.GroupId == (int)Group.Veldspar).OrderBy(i => i.Distance).FirstOrDefault();
                }


                if (asteroid == null)
                {
                    EmptyBelts.Add(_currentBelt.Id);
                    DirectBookmark asteroidShortcutBM2 = Cache.Instance.BookmarksByLabel("Asteroid Location").FirstOrDefault();

                    if (asteroidShortcutBM2 != null)
                    {
                        asteroidShortcutBM2.Delete();
                    }

                    Logging.Log("MiningBehavior", "Could not find a suitable Asteroid to mine in this belt.", Logging.White);
                    _States.CurrentMiningState = MiningState.GotoBelt;
                    break;
                }

                Logging.Log("Mining: [", "Target Rock is [" + asteroid.Name + "][" + Math.Round(asteroid.Distance / 1000, 0) + "k] ID [" + asteroid.MaskedId + "] GroupID [" + asteroid.GroupId + "]", Logging.White);
                _targetAsteroidID = asteroid.Id;
                _targetAsteroid.Approach();
                _States.CurrentMiningState = MiningState.MineAsteroid;
                break;

            case MiningState.MineAsteroid:
                if (Cache.Instance.EntityById(_targetAsteroidID) == null)
                {
                    Logging.Log("Mining: [", "Target Rock [" + Cache.Instance.MaskedID(_targetAsteroidID) + "] has been depleted. Searching for another target.", Logging.White);
                    _States.CurrentMiningState = MiningState.Mine;
                    return;
                }
                _targetAsteroid = Cache.Instance.EntityById(_targetAsteroidID);
                Combat.ProcessState();
                Drones.ProcessState();

                // If we are out of ammo, return to base, Arm should then grab the right ammo / crystals / drones
                if (_States.CurrentCombatState == CombatState.OutOfAmmo)
                {
                    Logging.Log("Combat", "Out of Ammo!", Logging.Orange);
                    _States.CurrentMiningState = MiningState.GotoBase;
                }

                //check if we're full

                //
                // we really ought to be checking for and using the OreHold if needed, not directly using the cargohold ffs!
                //
                if (Cache.Instance.CurrentShipsCargo == null)
                {
                    return;
                }

                if (Cache.Instance.CurrentShipsCargo.IsValid && (Cache.Instance.CurrentShipsCargo.UsedCapacity >= Cache.Instance.CurrentShipsCargo.Capacity * .9) && Cache.Instance.CurrentShipsCargo.Capacity > 0)
                {
                    if (_States.CurrentDroneState == DroneState.WaitingForTargets)
                    {
                        Logging.Log("Miner:MineAsteroid", "We are full, go to base to unload. Capacity is: " + Cache.Instance.CurrentShipsCargo.Capacity + ", Used: " + Cache.Instance.CurrentShipsCargo.UsedCapacity, Logging.White);
                        _States.CurrentMiningState = MiningState.GotoBase;
                        break;
                    }

                    if (_States.CurrentDroneState == DroneState.WaitingForTargets)
                    {
                        Logging.Log("Miner:MineAsteroid", "We are full, but drones are busy. Drone state: " + _States.CurrentDroneState.ToString(), Logging.White);
                    }
                }

                //
                // do we need to make sure the rock is in targeting range? rats that damp, frigates with crap skills?, wormhole effects...
                //
                if (_targetAsteroid.Distance < 10000)
                {
                    if (_targetAsteroid.Distance < 9400)
                    {
                        if (_asteroidBookmarkForID != _targetAsteroid.Id)
                        {
                            DirectBookmark asteroidShortcutBM = Cache.Instance.BookmarksByLabel("Asteroid Location").FirstOrDefault();

                            if (asteroidShortcutBM != null)
                            {
                                asteroidShortcutBM.UpdateBookmark("Asteroid Location", "Mining Shortcut");
                            }
                            else
                            {
                                Cache.Instance.DirectEve.BookmarkCurrentLocation("Asteroid Location", "Mining Shortcut", null);
                            }

                            _asteroidBookmarkForID = _targetAsteroid.Id;
                        }
                    }

                    if (Cache.Instance.Targeting.Contains(_targetAsteroid))
                    {
                        if (Settings.Instance.DebugMiningBehavior)
                        {
                            Logging.Log("Miner:MineAsteroid", "Targeting asteroid.", Logging.White);
                        }
                        return;
                        //wait
                    }

                    if (Cache.Instance.Targets.Contains(_targetAsteroid))
                    {
                        if (Settings.Instance.DebugMiningBehavior)
                        {
                            Logging.Log("Miner:MineAsteroid", "Asteroid Targeted.", Logging.White);
                        }
                        //if(!_targetAsteroid.IsActiveTarget) _targetAsteroid.MakeActiveTarget();
                        List <ModuleCache> miningTools = Cache.Instance.Modules.Where(m => MiningToolGroupIDs.Contains(m.GroupId)).ToList();

                        _minerNumber = 0;
                        foreach (ModuleCache miningTool in miningTools)
                        {
                            if (Cache.Instance.LastActivatedTimeStamp != null && Cache.Instance.LastActivatedTimeStamp.ContainsKey(miningTool.ItemId))
                            {
                                if (Cache.Instance.LastActivatedTimeStamp[miningTool.ItemId].AddSeconds(3) > DateTime.UtcNow)
                                {
                                    continue;
                                }
                            }

                            _minerNumber++;

                            // Are we on the right target?
                            if (miningTool.IsActive)
                            {
                                if (miningTool.TargetId != _targetAsteroid.Id)
                                {
                                    if (miningTool.Click())
                                    {
                                        return;
                                    }

                                    return;
                                }
                                continue;
                            }

                            // Are we deactivating?
                            if (miningTool.IsDeactivating)
                            {
                                continue;
                            }

                            if (miningTool.Activate(_targetAsteroid))
                            {
                                //only activate one module per cycle
                                Logging.Log("Mining", "Activating mining tool [" + _minerNumber + "] on [" + _targetAsteroid.Name + "][" + Cache.Instance.MaskedID(_targetAsteroid.Id) + "][" + Math.Round(_targetAsteroid.Distance / 1000, 0) + "k away]", Logging.Teal);
                                return;
                            }

                            continue;
                        }

                        return;
                    }     //mine

                    //asteroid is not targeted
                    if (Settings.Instance.DebugMiningBehavior)
                    {
                        Logging.Log("Miner:MineAsteroid", "Asteroid not yet targeted.", Logging.White);
                    }
                    if (DateTime.UtcNow < Cache.Instance.NextTargetAction)     //if we just did something wait a fraction of a second
                    {
                        return;
                    }

                    if (Cache.Instance.MaxLockedTargets == 0)
                    {
                        if (!_isJammed)
                        {
                            Logging.Log("Mining", "We are jammed and can't target anything", Logging.Orange);
                        }

                        _isJammed = true;
                        return;
                    }

                    if (_isJammed)
                    {
                        // Clear targeting list as it does not apply
                        Cache.Instance.TargetingIDs.Clear();
                        Logging.Log("Mining", "We are no longer jammed, ReTargeting", Logging.Teal);
                    }
                    _isJammed = false;

                    _targetAsteroid.LockTarget("Mining.targetAsteroid");
                    Cache.Instance.NextTargetAction = DateTime.UtcNow.AddMilliseconds(Time.Instance.TargetDelay_milliseconds);
                    return;
                }     //check 10K distance

                //
                // not inside 10k
                //
                if (Settings.Instance.DebugMiningBehavior)
                {
                    Logging.Log("Miner:MineAsteroid", "Debug: Distance to Target [" + Math.Round(_targetAsteroid.Distance / 1000, 2) + "] > 10K.] Id [" + _targetAsteroid.Id + "] TargetingMe [" + Combat.TargetingMe.Count() + "]", Logging.White);
                }
                //this isn't working because Cache.Instance.Approaching.TargetValue always seems to return null. This will negatively impact combat since it won't orbit. Might want to check CombatState instead.
                if (Cache.Instance.IsApproaching(_targetAsteroidID) && !Cache.Instance.TargetedBy.Any())
                {
                    //
                    // this will only approach every 15 sec
                    //
                    _targetAsteroid.Approach();
                }


                break;
            } //ends MiningState switch
        }     //ends ProcessState method