예제 #1
0
        private async Task <bool> SetUsedGatesToIgnored()
        {
            // 'Reference' positions are hardcoded gate positions by SceneSnoId.
            // These allow gate nativation as soon as a scene is discovered.
            // And may be slightly off from actual gate actor positions.

            if (_deathGate != null)
            {
                Core.Logger.Debug($"Added origin gate to ignore list. (DiaGizmo) {_deathGate.Position}");
                _deathGateIgnoreList[_deathGate.Position] = DateTime.UtcNow;
            }

            if (_deathGate?.Position != _deathGatePosition)
            {
                Core.Logger.Debug($"Added origin gate position to ignore list. (Reference) {_deathGatePosition}");
                _deathGateIgnoreList[_deathGatePosition] = DateTime.UtcNow;
            }

            var destinationGate = ActorFinder.FindNearestDeathGate();

            if (destinationGate != null)
            {
                Core.Logger.Debug($"Added destination gate to ignore list (DiaGizmo) {destinationGate}");
                _deathGateIgnoreList[destinationGate.Position] = DateTime.UtcNow;
            }

            var destinationGateReferencePosition = DeathGates.NearestGateToPosition(AdvDia.MyPosition);

            if (destinationGateReferencePosition != Vector3.Zero)
            {
                Core.Logger.Debug($"Added destination gate to ignore list (Reference) {destinationGateReferencePosition}");
                _deathGateIgnoreList[destinationGateReferencePosition] = DateTime.UtcNow;
            }

            return(false);
        }
        private async Task <bool> Interacting()
        {
            var startSide = DeathGates.MySide;
            var startGate = ActorFinder.FindNearestDeathGate();

            if (startGate == null)
            {
                Core.Logger.Debug("Can't find a gate nearby");
                State = States.Failed;
                return(false);
            }
            if (startGate.Distance > startGate.CollisionSphere.Radius)
            {
                Core.Logger.Debug("Gate is too far away to interact");
                State = States.MovingToGate;
                return(false);
            }

            if (_interactionCoroutine == null || _interactionCoroutine.IsDone)
            {
                Core.Logger.Debug($"Interacting with {startGate.Name} at {startGate.Position} Distance={startGate.Distance} CurrentScene={CurrentGateScene}");
                _interactionCoroutine = new InteractionCoroutine(startGate.ActorSnoId, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(1), 5);
            }

            if (!await _interactionCoroutine.GetCoroutine())
            {
                return(false);
            }

            if (_interactionCoroutine.State == InteractionCoroutine.States.Failed)
            {
                Core.Logger.Debug("InteractionCoroutine reports interaction with gate failed");
                State = States.Failed;
                return(false);
            }

            if (TargetGatePosition.Distance(AdvDia.MyPosition) <= 10f)
            {
                Core.Logger.Debug("Interaction with gate failed, we didnt move anywhere.");
                State = States.Failed;
                return(false);
            }

            _gatesUsed++;

            //var endGateInteractPos = DeathGates.NearestGateToPosition(endGate.Position);
            var endGateInteractPos = CurrentGateScene.PortalPositions.FirstOrDefault(p => p != TargetGatePosition);

            Core.Logger.Debug($"Ignoring Gate at {endGateInteractPos} within {CurrentGateScene.Name} {DeathGates.MySide}");
            _usedGatePositions.Add(endGateInteractPos);

            Core.Logger.Debug($"Ignoring Gate at {TargetGatePosition} within {CurrentGateScene.Name} {startSide}");
            _usedGatePositions.Add(TargetGatePosition);

            Core.Logger.Debug($"Gate #{_gatesUsed} at {TargetGatePosition} within {CurrentGateScene.Name} ({startSide}=>{DeathGates.MySide}) was used successfully");
            if (_gatesToUse >= 0 && _gatesUsed >= _gatesToUse)
            {
                Core.Logger.Debug($"We've used all the gates we're supposed to ({_gatesUsed})");
                State = States.Completed;
                return(false);
            }
            State = States.Searching;
            return(false);
        }
예제 #3
0
        private async Task <bool> Moving()
        {
            // Account for portals directly below current terrain.
            var zDiff = Math.Abs((float)(Destination.Z - AdvDia.MyPosition.Z));
            var distanceToDestination = AdvDia.MyPosition.Distance(Destination);

            if (_timeout == DateTime.MaxValue)
            {
                _timeout = DateTime.UtcNow + TimeSpan.FromSeconds(240);
            }

            //if (_mover == Mover.StraightLine && (!Core.Grids.CanRayWalk(AdvDia.MyPosition, Destination) || !await AdvDia.Navigator.CanFullyClientPathTo(Destination)))
            //{
            //    Core.Logger.Debug("Unable to straight line path, switching to navigator pathing");
            //    _mover = Mover.Navigator;
            //}

            if (Destination != Vector3.Zero)
            {
                if (_distance != 0 && distanceToDestination <= _distance && zDiff < 4 || Core.Player.IsDead && !Core.Player.IsGhosted)
                {
                    Navigator.PlayerMover.MoveStop();
                    LastMoveResult = MoveResult.ReachedDestination;
                }
                else
                {
                    //if (_mover == Mover.StraightLine && PluginTime.ReadyToUse(_lastRaywalkCheck, 200))
                    //{
                    //    if (!Core.Grids.CanRayWalk(AdvDia.MyPosition, Destination))
                    //    {
                    //        _mover = Mover.Navigator;
                    //    }
                    //    _lastRaywalkCheck = PluginTime.CurrentMillisecond;
                    //}
                    switch (_mover)
                    {
                    case Mover.StraightLine:
                        Navigator.PlayerMover.MoveTowards(Destination);
                        LastMoveResult = MoveResult.Moved;
                        Core.Logger.Debug($"MoveTowards Destination={Destination} Dist3D={AdvDia.MyPosition.Distance(Destination)} Dist2D={AdvDia.MyPosition.Distance2D(Destination)}");
                        return(false);

                    case Mover.Navigator:
                        if (AdvDia.Navigator != null)
                        {
                            LastMoveResult = await AdvDia.Navigator.MoveTo(Destination);
                        }
                        else
                        {
                            LastMoveResult = await Navigator.MoveTo(Destination);
                        }
                        Core.Logger.Debug($"Navigator MoveResult = {LastMoveResult}, Destination={Destination} Dist3D={AdvDia.MyPosition.Distance(Destination)} Dist2D={AdvDia.MyPosition.Distance2D(Destination)}");
                        break;
                    }
                }
                switch (LastMoveResult)
                {
                case MoveResult.ReachedDestination:

                    if (_distance != 0 && distanceToDestination <= _distance || distanceToDestination <= 5f)
                    {
                        Core.Logger.Debug("Completed (Distance to destination: {0})", distanceToDestination);
                        State = States.Completed;
                    }
                    else
                    {
                        // DB Navigator will report ReachedDestination when failing to navigate to positions that require a death gate to reach. Redirect to gate position.
                        if (Core.Rift.IsInRift && ActorFinder.FindNearestDeathGate() != null)
                        {
                            Core.Logger.Debug($"Starting Death Gate Sequence.");
                            State = States.MovingToDeathGate;
                        }
                        else
                        {
                            Core.Logger.Debug($"Navigator reports DestinationReached but we're not at destination, failing. Mover={_mover}");
                            State          = States.LastResortMovement;
                            LastMoveResult = MoveResult.Failed;
                        }
                    }
                    return(false);

                case MoveResult.Failed:
                    Core.Logger.Debug($"Navigator reports Failed movement attempt. Mover={_mover}");
                    State = States.LastResortMovement;
                    return(false);

                    break;

                case MoveResult.PathGenerationFailed:
                    Core.Logger.Debug("[Navigation] Path generation failed.");
                    Core.PlayerMover.MoveTowards(Destination);
                    if (distanceToDestination < 100 && Core.Grids.CanRayWalk(AdvDia.MyPosition, Destination))
                    {
                        _mover = Mover.StraightLine;
                        return(false);
                    }
                    State = States.Failed;
                    return(false);

                case MoveResult.UnstuckAttempt:
                    await Navigator.StuckHandler.DoUnstick();

                    if (_unstuckAttemps > 3)
                    {
                        State = States.Failed;
                        return(false);
                    }
                    _unstuckAttemps++;
                    Core.Logger.Debug("[Navigation] Unstuck attempt #{0}", _unstuckAttemps);
                    break;

                case MoveResult.PathGenerated:
                case MoveResult.Moved:
                    break;

                case MoveResult.PathGenerating:
                    if (_pathGenetionTimer.IsFinished)
                    {
                        Core.Logger.Log("Patiently waiting for the Navigation Server");
                        _pathGenetionTimer.Reset();
                    }
                    break;
                }
                return(false);
            }
            State = States.Completed;
            return(false);
        }
예제 #4
0
        private async Task <bool> Interacting()
        {
            if (ZetaDia.Me.IsFullyValid() && (_castWaitStartTime.Subtract(DateTime.UtcNow).TotalSeconds < 10 || _castWaitStartTime == DateTime.MinValue))
            {
                if (ZetaDia.Me.CommonData.AnimationState == AnimationState.Casting)
                {
                    _castWaitStartTime = DateTime.UtcNow;
                    Core.Logger.Debug("Waiting while AnimationState.Casting");
                    await Coroutine.Sleep(500);

                    return(false);
                }
                if (ZetaDia.Me.CommonData.AnimationState == AnimationState.Channeling)
                {
                    _castWaitStartTime = DateTime.UtcNow;
                    Core.Logger.Debug("Waiting while  AnimationState.Channeling");
                    await Coroutine.Sleep(500);

                    return(false);
                }
            }

            if (ZetaDia.Globals.IsLoadingWorld)
            {
                Core.Logger.Debug("Waiting for world load");
                await Coroutine.Sleep(500);

                return(false);
            }

            if (ZetaDia.Globals.WorldSnoId != _startingWorldId)
            {
                Core.Logger.Debug("World changed, assuming done!");
                await Coroutine.Sleep(2500);

                State = States.Completed;
                return(false);
            }

            var actor = GetActor();

            if (actor == null)
            {
                Core.Logger.Debug("Nothing to interact, failing. ");
                State = States.Failed;
                return(false);
            }

            if (!string.IsNullOrEmpty(_endAnimation))
            {
                var anim = actor.CommonData?.CurrentAnimation.ToString().ToLowerInvariant();
                if (!string.IsNullOrEmpty(anim) && anim.Contains(_endAnimation.ToLowerInvariant()))
                {
                    Core.Logger.Debug($"Specified end animation was detected {_endAnimation}, done!");
                    State = States.Completed;
                    return(false);
                }
            }

            if (!string.IsNullOrEmpty(_startAnimation))
            {
                var anim = actor.CommonData?.CurrentAnimation.ToString().ToLowerInvariant();
                if (!string.IsNullOrEmpty(anim) && !anim.Contains(_startAnimation.ToLowerInvariant()))
                {
                    Core.Logger.Debug($"Specified start animation was no longer detected {_startAnimation}, done!");
                    State = States.Completed;
                    return(false);
                }
            }

            var unit = actor as DiaUnit;

            if (_isQuestGiver && unit != null && !unit.IsQuestGiver)
            {
                Core.Logger.Debug($"Unit {actor.Name} is no longer a quest giver, assuming done!");
                State = States.Completed;
                return(false);
            }

            //if (actor.Distance > 75f)
            //{
            //    Core.Logger.Debug($"Actor is way too far away. {actor.Distance}");
            //    State = States.Failed;
            //    return false;
            //}

            // Assume done
            if (!_ignoreSanityChecks && !actor.IsInteractableQuestObject())
            {
                State = States.Completed;
                return(false);
            }

            if (_currentInteractAttempt > _interactAttempts)
            {
                Core.Logger.Debug($"Max interact attempts reached ({_interactAttempts})");
                State = States.Completed;
                return(true);
            }

            if (_currentInteractAttempt > 1 && actor.Position.Distance(ZetaDia.Me.Position) > 5f)
            {
                Navigator.PlayerMover.MoveTowards(actor.Position);
                await Coroutine.Sleep(250 *_currentInteractAttempt);
            }

            if (_isPortal || actor.IsFullyValid() && GameData.PortalTypes.Contains(actor.CommonData.GizmoType))
            {
                var worldId = ZetaDia.Globals.WorldSnoId;
                if (worldId != _startingWorldId)
                {
                    Core.Logger.Debug($"World changed from {_startingWorldId} to {worldId}, assuming done.");
                    State = States.Completed;
                    return(true);
                }
            }

            if (_timeoutCheckEnabled)
            {
                if (_interactionStartedAt == default(DateTime))
                {
                    _interactionStartedAt = DateTime.UtcNow;
                }
                else
                {
                    if (DateTime.UtcNow - _interactionStartedAt > _timeOut)
                    {
                        Core.Logger.Debug("Interaction timed out after {0} seconds", (DateTime.UtcNow - _interactionStartedAt).TotalSeconds);
                        State = States.TimedOut;
                        return(false);
                    }
                }
            }

            if (!actor.IsFullyValid())
            {
                Core.Logger.Debug($"Actor is no longer valid, assuming done.");
                State = States.Completed;
                return(true);
            }

            Core.Logger.Debug($"Attempting to interact with {((SNOActor)actor.ActorSnoId)} at distance {actor.Distance} #{_currentInteractAttempt}");

            var interactionResult = await Interact(actor);

            await Coroutine.Sleep(300);

            if (ActorFinder.IsDeathGate(actor))
            {
                var nearestGate = ActorFinder.FindNearestDeathGate();
                if (nearestGate.CommonData.AnnId != actor.CommonData.AnnId && actor.Distance > 10f)
                {
                    Core.Logger.Debug("Arrived at Gate Destination (AnnId Check)");
                    State = States.Completed;
                    return(true);
                }
            }

            //// Sleep time would have to be set to 0/low for this to be checked during gate travel.
            //if (ZetaDia.Me.IsUsingDeathGate())
            //{
            //    Core.Logger.Debug("Used Death Gate!");
            //    await Coroutine.Wait(5000, () => !ZetaDia.Me.IsUsingDeathGate());
            //    Core.Logger.Debug("Arrived at Gate Destination (Travelling Check)");
            //    State = States.Completed;
            //    return true;
            //}

            if (interactionResult)
            {
                if (_currentInteractAttempt <= _interactAttempts)
                {
                    _currentInteractAttempt++;
                    return(false);
                }
                if (!_isPortal && !_isNephalemStone && !_isOrek && actor.IsInteractableQuestObject())
                {
                    return(false);
                }
                if (_isNephalemStone && !UIElements.RiftDialog.IsVisible)
                {
                    return(false);
                }
                if (_isOrek && AdvDia.RiftQuest.State != QuestState.Completed)
                {
                    return(false);
                }
                State = States.Completed;
            }

            Core.Logger.Debug($"Interaction Failed");
            return(false);
        }
예제 #5
0
        private void ScanForObjective()
        {
            if (_previouslyFoundLocation != Vector3.Zero && PluginTime.ReadyToUse(_returnTimeForPreviousLocation, 60000))
            {
                _objectiveLocation             = _previouslyFoundLocation;
                _previouslyFoundLocation       = Vector3.Zero;
                _returnTimeForPreviousLocation = PluginTime.CurrentMillisecond;
                Core.Logger.Debug("[EnterLevelArea] Returning previous objective location.");

                return;
            }
            if (PluginTime.ReadyToUse(_lastScanTime, 250))
            {
                _lastScanTime = PluginTime.CurrentMillisecond;
                if (_portalMarker != 0)
                {
                    if (_objectiveLocation == Vector3.Zero)
                    {
                        // Help with weighting exploration nodes even if its unreachable/unpathable.
                        var markerlocation = BountyHelpers.ScanForMarkerLocation(_portalMarker, 5000);
                        ExplorationHelpers.SetExplorationPriority(markerlocation);
                    }

                    _objectiveLocation = BountyHelpers.ScanForMarkerLocation(_portalMarker, _objectiveScanRange);

                    if (ExplorationData.FortressLevelAreaIds.Contains(AdvDia.CurrentLevelAreaId))
                    {
                        _deathGateLocation = DeathGates.GetBestGatePosition(_objectiveLocation);
                        if (_deathGateLocation != Vector3.Zero)
                        {
                            if (Navigator.StuckHandler.IsStuck && _deathGateLocation.Distance(AdvDia.MyPosition) < 125f)
                            {
                                var nearestGate = ActorFinder.FindNearestDeathGate();
                                if (nearestGate != null)
                                {
                                    Core.Logger.Warn("Found death gate location");
                                    _objectiveLocation = nearestGate.Position;
                                }
                            }
                        }
                    }
                }
                if (_objectives != null && _objectives.Any())
                {
                    BountyHelpers.ObjectiveActor objective;
                    _objectiveLocation = BountyHelpers.TryFindObjectivePosition(_objectives, _objectiveScanRange, out objective);
                    if (objective != null)
                    {
                        _objective          = objective;
                        _portalActorId      = objective.ActorId;
                        _destinationWorldId = objective.DestWorldId;
                    }
                }
                // Belial
                if (_objectiveLocation == Vector3.Zero && _portalActorId == 159574)
                {
                    _objectiveLocation = BountyHelpers.ScanForActorLocation(_portalActorId, _objectiveScanRange);
                }
                //if (_objectiveLocation == Vector3.Zero && _portalActorId != 0)
                //{
                //    _objectiveLocation = BountyHelpers.ScanForActorLocation(_portalActorId, _objectiveScanRange);
                //}
                if (_objectiveLocation != Vector3.Zero)
                {
                    Core.Logger.Log("[EnterLevelArea] Found the objective at distance {0}", AdvDia.MyPosition.Distance(_objectiveLocation));
                    ExplorationHelpers.SetExplorationPriority(_objectiveLocation);
                }
            }
        }
예제 #6
0
        private async Task <bool> MovingToDeathGate()
        {
            if (_deathGate != null && _deathGate.IsFullyValid())
            {
                if (AdvDia.MyPosition.Distance(_deathGate.Position) <= 7f)
                {
                    Navigator.PlayerMover.MoveStop();
                    MoveResult = MoveResult.ReachedDestination;
                }
                else
                {
                    _deathGate = ActorFinder.FindNearestDeathGate(_deathGateIgnoreList);
                    if (_deathGate == null)
                    {
                        MoveResult = MoveResult.Failed;
                        State      = States.Failed;
                        return(false);
                    }
                    MoveResult = await CommonCoroutines.MoveTo(_deathGate.Position);
                }
                switch (MoveResult)
                {
                case MoveResult.ReachedDestination:
                    var distance = AdvDia.MyPosition.Distance(_deathGate.Position);
                    if (distance <= 7f)
                    {
                        _interactionCoroutine = new InteractionCoroutine(_deathGate.ActorSnoId, new TimeSpan(0, 0, 1), new TimeSpan(0, 0, 3));
                        State = States.InteractingWithDeathGate;
                    }
                    else
                    {
                        _deathGateIgnoreList.Add(_deathGate.ACDId);
                        State = States.Moving;
                    }
                    break;

                case MoveResult.Failed:
                case MoveResult.PathGenerationFailed:
                    State = States.Failed;
                    break;

                case MoveResult.PathGenerated:
                    break;

                case MoveResult.UnstuckAttempt:
                    if (_unstuckAttemps > 1)
                    {
                        State = States.Failed;
                        return(false);
                    }
                    _unstuckAttemps++;
                    Logger.Debug("[Navigation] Unstuck attempt #{0}", _unstuckAttemps);
                    break;

                case MoveResult.Moved:
                case MoveResult.PathGenerating:
                    break;
                }
                return(false);
            }
            State = States.Failed;
            return(false);
        }
예제 #7
0
        private async Task <bool> Moving()
        {
            var distanceToDestination = AdvDia.MyPosition.Distance(_destination);

            if (_destination != Vector3.Zero)
            {
                if (_distance != 0 && distanceToDestination <= _distance)
                {
                    Navigator.PlayerMover.MoveStop();
                    MoveResult = MoveResult.ReachedDestination;
                }
                else
                {
                    if (_mover == Mover.StraightLine && PluginTime.ReadyToUse(_lastRaywalkCheck, 200))
                    {
                        if (!NavigationGrid.Instance.CanRayWalk(AdvDia.MyPosition, _destination))
                        {
                            _mover = Mover.Navigator;
                        }
                        _lastRaywalkCheck = PluginTime.CurrentMillisecond;
                    }
                    switch (_mover)
                    {
                    case Mover.StraightLine:
                        Navigator.PlayerMover.MoveTowards(_destination);
                        MoveResult = MoveResult.Moved;
                        return(false);

                    case Mover.Navigator:
                        MoveResult = await Navigator.MoveTo(_destination);

                        break;
                    }
                }
                switch (MoveResult)
                {
                case MoveResult.ReachedDestination:
                    if ((_distance != 0 && distanceToDestination <= _distance) || distanceToDestination <= 7f)
                    {
                        Logger.Debug("[Navigation] Completed (Distance to destination: {0})", distanceToDestination);
                        State = States.Completed;
                    }
                    else
                    {
                        _deathGate = ActorFinder.FindNearestDeathGate(_deathGateIgnoreList);
                        if (_deathGate != null)
                        {
                            State = States.MovingToDeathGate;
                        }
                        else
                        {
                            State      = States.Failed;
                            MoveResult = MoveResult.Failed;
                        }
                    }
                    return(false);

                case MoveResult.Failed:
                    break;

                case MoveResult.PathGenerationFailed:

                    var navProvider = Navigator.NavigationProvider as DefaultNavigationProvider;
                    if (navProvider != null)
                    {
                        Logger.Debug("[Navigation] Path generation failed.");
                        navProvider.Clear();
                    }
                    if (distanceToDestination < 100 &&
                        NavigationGrid.Instance.CanRayWalk(AdvDia.MyPosition, _destination))
                    {
                        _mover = Mover.StraightLine;
                        return(false);
                    }
                    State = States.Failed;
                    return(false);

                case MoveResult.UnstuckAttempt:
                    if (_unstuckAttemps > 1)
                    {
                        State = States.Failed;
                        return(false);
                    }
                    _unstuckAttemps++;
                    Logger.Debug("[Navigation] Unstuck attempt #{0}", _unstuckAttemps);
                    break;

                case MoveResult.PathGenerated:
                case MoveResult.Moved:
                    break;

                case MoveResult.PathGenerating:
                    if (_pathGenetionTimer.IsFinished)
                    {
                        Logger.Info("Patiently waiting for the Navigation Server");
                        _pathGenetionTimer.Reset();
                    }
                    break;
                }
                return(false);
            }
            State = States.Completed;
            return(false);
        }