public void RemoveFromQueues(string regionName, object key) { var injectionItem = InjectionQueue.FirstOrDefault(x => x.RegionName == regionName && object.Equals(x.Key, key)); injectionItem.Do(x => InjectionQueue.Remove(x)); var persistentInjectionItem = PersistentInjectionQueue.FirstOrDefault(x => x.RegionName == regionName && object.Equals(x.Key, key)); persistentInjectionItem.Do(x => PersistentInjectionQueue.Remove(x)); var navigationItem = NavigationQueue.FirstOrDefault(x => x.RegionName == regionName && object.Equals(x.Key, key)); navigationItem.Do(x => NavigationQueue.Remove(x)); }
public bool GotoNode(NavigationNode target_node) { NavigationNode nearest_node = null; float min_dist = float.MaxValue; foreach (NavigationNode node in NavigationNode.AllNodes.Values) { if (node.LinkedNodes.Count > 0) { float new_dist = Vector3.Distance(NPCPlayer.Position, node.Position); if (new_dist < min_dist) { min_dist = new_dist; nearest_node = node; } } } if (nearest_node != null) { Log.Debug($"[NAV] Selected nearest node: {nearest_node.Name}", Plugin.Instance.Config.VerboseOutput); Dictionary <NavigationNode, int> visited = new Dictionary <NavigationNode, int>(); TryProcessNode(target_node, nearest_node, -1, ref visited); if (!visited.ContainsKey(target_node)) { Log.Debug("[NAV] Failed to build way", Plugin.Instance.Config.VerboseOutput); return(false); } else { NavigationQueue.Clear(); NavigationNode cur = target_node; Log.Debug("[NAV] Built way:", Plugin.Instance.Config.VerboseOutput); do { Log.Debug($"[NAV] {cur.Name}", Plugin.Instance.Config.VerboseOutput); NavigationQueue.AddFirst(cur); cur = FindNextNode(cur, visited); } while (cur != null); return(true); } } else { Log.Error("[NAV] Failed to find nearest navnode"); return(false); } }
public void PutToNavigationQueue(string regionName, object key) { NavigationQueue.Add(new NavigationItem(regionName, key)); }
/// <summary> /// /// </summary> /// <param name="current"></param> /// <param name="queue"></param> /// <returns></returns> protected virtual Task OnNavigationAsync(NavigationItem current, NavigationQueue queue) { return(Task.CompletedTask); }
Task IAtomNavigationAware.OnNavigatedAsync(NavigationItem current, NavigationQueue queue) { return(OnNavigationAsync(current, queue)); }
public NavigationManager(AppViewModel parent) { _rootFrame = App.Current.RootFrame; _parent = parent; _queue = new NavigationQueue(this); }
public void ClearNavTargets() { NavigationQueue.Clear(); CurrentNavTarget = null; }
public void AddNavTarget(NavigationNode node) { NavigationQueue.AddLast(node); }
private IEnumerator <float> NavCoroutine() { Queue <Vector3> FollowTargetPosCache = new Queue <Vector3>(); int eta = 0; int dormant_cache_update = 0; for (; ;) { if (FollowTarget != null) { if (FollowTarget.IsAlive) { float dist = Vector3.Distance(FollowTarget.Position, NPCPlayer.Position); //If we are far away... if (dist >= Plugin.Instance.Config.MaxFollowDistance) { if (OnTargetLostBehaviour == TargetLostBehaviour.TELEPORT) { //... Teleport to player if allowed NPCPlayer.Position = FollowTarget.Position; eta = 0; FollowTargetPosCache.Clear(); } else { //Stop or try to search otherwise FireEvent(new NPCTargetLostEvent(this, FollowTarget)); FollowTargetPosCache.Clear(); eta = 0; Stop(); if (OnTargetLostBehaviour == TargetLostBehaviour.SEARCH) { Room r = FollowTarget.CurrentRoom; if (r != null) { GotoRoom(r); } } continue; } } //If target is not near if (dist >= 1.5f) { //Update Pos cache each third tick if (dormant_cache_update > 2) { FollowTargetPosCache.Enqueue(FollowTarget.Position); dormant_cache_update = 0; } dormant_cache_update++; } else { //Otherwise just dont move FollowTargetPosCache.Clear(); eta = 0; Timing.KillCoroutines(MovementCoroutines.ToArray()); Move(MovementDirection.NONE); } } else { // Target dead, reset FollowTargetPosCache.Clear(); eta = 0; FireEvent(new NPCFollowTargetDiedEvent(this, FollowTarget)); Stop(); continue; } //If we reached predicted target if (eta <= 0) { //Schedule next position if (!FollowTargetPosCache.IsEmpty()) { float full_eta = GoTo(FollowTargetPosCache.Dequeue()); eta = (int)(full_eta / Plugin.Instance.Config.NavUpdateFrequency) - 1; } } else { eta--; } } else { //Noone to follow, try taking nodes from nav queue eta = 0; FollowTargetPosCache.Clear(); if (CurrentNavTarget != null) { IsRunning = !DisableRun; //There is current float distance = Vector3.Distance(CurrentNavTarget.Position, NPCPlayer.Position); if (distance < 3f && (!ProcessSCPLogic || NPCPlayer.Role != RoleType.Scp106)) { //Try to open the door if there is one, so we wont collide with it if (CurrentNavTarget.AttachedDoor != null && !CurrentNavTarget.AttachedDoor.NetworkisOpen) { ItemType prev = ItemHeld; bool open = NPCPlayer.IsBypassModeEnabled || (CurrentNavTarget.AttachedDoor.CheckpointDoor && NPCPlayer.ReferenceHub.characterClassManager.IsAnyScp()); if (!open) { if (!CurrentNavTarget.AttachedDoor.CanBeOpenedWith(ItemHeld)) { foreach (ItemType keycard in AvailableKeycards) { if (CurrentNavTarget.AttachedDoor.CanBeOpenedWith(keycard)) { ItemHeld = keycard; open = true; break; } } } else { open = true; } } if (open) { //All is good Timing.KillCoroutines(MovementCoroutines.ToArray()); Move(MovementDirection.NONE); while (CurrentNavTarget.AttachedDoor.locked) { yield return(0f); } yield return(Timing.WaitForSeconds(0.2f)); CurrentNavTarget.AttachedDoor.NetworkisOpen = true; yield return(Timing.WaitForSeconds(0.1f)); GoTo(CurrentNavTarget.Position); ItemHeld = prev; } else { //Stop otherwise Stop(); continue; } } } if (distance < 6) { NavigationNode NextNavTarget = NavigationQueue.First?.Value; NavigationNode lift_node = null; if (NextNavTarget != null) { if (NextNavTarget.AttachedElevator != null) { lift_node = NextNavTarget; } } //If there is an elevator, try to use it if (CurrentNavTarget.AttachedElevator == null && lift_node != null) { bool val = lift_node.AttachedElevator.Value.Value.IsClosed(lift_node.AttachedElevator.Value.Key); if (val) { lift_node.AttachedElevator.Value.Value.UseLift(); Timing.KillCoroutines(MovementCoroutines.ToArray()); Move(MovementDirection.NONE); while (!lift_node.AttachedElevator.Value.Value.operative) { yield return(0.0f); } GoTo(CurrentNavTarget.Position); } } } if (CurMovementDirection == MovementDirection.NONE) { //Target reached - force position to it so we wont stuck Vector3 forced = new Vector3(CurrentNavTarget.Position.x, NPCPlayer.Position.y, CurrentNavTarget.Position.z); NPCPlayer.ReferenceHub.playerMovementSync.OverridePosition(forced, 0f, true); //If we have AI item target reached, try to find and take item if (CurrentAIItemNodeTarget != null && CurrentAIItemNodeTarget == CurrentNavTarget) { CurrentAIItemNodeTarget = null; IEnumerable <Pickup> pickups = FindObjectsOfType <Pickup>().Where(pk => Vector3.Distance(pk.Networkposition, NPCPlayer.Position) <= 5f); foreach (Pickup p in pickups) { if (Utils.Utils.CheckItemType(CurrentAIItemGroupTarget, p.ItemId)) { yield return(Timing.WaitForSeconds(GoTo(p.position))); TakeItem(p); break; } } CurrentAIItemGroupTarget = null; } CurrentNavTarget = null; } } else if (NavigationQueue.Count > 0) { //No current, but there are pending targets CurrentNavTarget = NavigationQueue.First.Value; NavigationQueue.RemoveFirst(); if (CurrentNavTarget.AttachedElevator != null && Math.Abs(CurrentNavTarget.AttachedElevator.Value.Key.target.position.y - NPCPlayer.Position.y) > 2f) { CurrentNavTarget.AttachedElevator.Value.Value.UseLift(); while (CurrentNavTarget.AttachedElevator.Value.Value.status == Lift.Status.Moving) { yield return(0f); } CurrentNavTarget = null; } else { GoTo(CurrentNavTarget.Position); } } else if (CurrentAIRoomTarget != null) { //No current, no pending - room reached CurrentAIRoomTarget = null; } } yield return(Timing.WaitForSeconds(Plugin.Instance.Config.NavUpdateFrequency)); } }