IEnumerator MakeMoveCoroutine(Move move, System.Action callback) { var pawnDisplay = GetPawnDisplay(move.PawnPos); var pawn = pawnDisplay.Pawn; var newPos = move.NewPos.ToVector2(); pawnDisplay.MoveToFront(); var movementCoroutine = MovementCoroutines.SmoothlyMove(pawnDisplay.transform.position, newPos, 0.5f); foreach (var pos in movementCoroutine) { pawnDisplay.transform.position = pos; yield return(new WaitForEndOfFrame()); } pawnDisplay.MoveToBack(); pawnDisplay.transform.position = newPos; if (move.NewPos.y == 0 && Gameplay.Instance.LowerPawnsColor != pawn.Color || move.NewPos.y == 7 && Gameplay.Instance.LowerPawnsColor == pawn.Color) { pawnDisplay.SetKing(); } if (move.IsATake) { var takenPawn = GetPawnDisplay(move.TakePos.Value, tryGet: true); pawns.Remove(takenPawn); takenPawn.TakeDown(); } callback(); }
IEnumerator ResetCamera(float Duration, Vector3 newCamPosition = default(Vector3)) { IsMovingInternal = true; StartCoroutine( MovementCoroutines.MoveLerpTo(gameObject, newCamPosition, Duration) ); StartCoroutine( MovementCoroutines.MoveLerpLocalTo( CameraObject, new Vector3(0, 0, OriginalZoomAxis), Duration ) ); Quaternion OriginalVerticalQuat = Quaternion.Euler(new Vector3(OriginalVerticalAxis, 0, 0)); Quaternion OriginalHorizontalQuat = Quaternion.Euler(new Vector3(0, OriginalHorizontalAxis, 0)); StartCoroutine( MovementCoroutines.RotateLerpLocalTo(VerticalRig, OriginalVerticalQuat, Duration) ); StartCoroutine( MovementCoroutines.RotateLerpTo(gameObject, OriginalHorizontalQuat, Duration) ); ZoomAxis = OriginalZoomAxis; VerticalAxis = OriginalVerticalAxis; HorizontalAxis = OriginalHorizontalAxis; ElevateAxis = OriginalElevateAxis; yield return(new WaitForSeconds(Duration)); IsMovingInternal = false; }
public float GoTo(Vector3 position) { IsActionLocked = true; Timing.KillCoroutines(MovementCoroutines.ToArray()); Vector3 heading = (position - NPCPlayer.Position); heading.y = 0; Quaternion lookRot = Quaternion.LookRotation(heading.normalized); float dist = heading.magnitude; NPCPlayer.Rotations = new Vector2(lookRot.eulerAngles.x, lookRot.eulerAngles.y); Move(MovementDirection.FORWARD); float eta = Plugin.Instance.Config.MovementUpdateFrequency * (dist / (NPCPlayer.CameraTransform.forward / 10 * MovementSpeed).magnitude); position.y = NPCPlayer.Position.y; MovementCoroutines.Add(Timing.CallDelayed(eta, () => { Move(MovementDirection.NONE); if (Vector3.Distance(NPCPlayer.Position, position) >= 2f) { NPCPlayer.ReferenceHub.playerMovementSync.OverridePosition(position, 0f, true); } IsActionLocked = false; })); return(eta); }
public void Stop() { ClearNavTargets(); FollowTarget = null; CurrentAIRoomTarget = null; CurrentAIItemNodeTarget = null; CurrentAIItemGroupTarget = null; Timing.KillCoroutines(MovementCoroutines.ToArray()); Move(MovementDirection.NONE); }
private void OnDestroy() { Dictionary.Remove(this.gameObject); Timing.KillCoroutines(MovementCoroutines.ToArray()); Timing.KillCoroutines(AttachedCoroutines.ToArray()); Log.SendRaw($"NPC {NPCPlayer.Nickname} ({NPCPlayer.Id}) deconstructed", ConsoleColor.Green); Player.IdsCache.Remove(NPCPlayer.Id); Player.Dictionary.Remove(NPCPlayer.GameObject); }
//Move Tween IEnumerator MoveTo(Vector3 Point, float Duration) { IsMovingInternal = true; StartCoroutine( MovementCoroutines.MoveLerpTo(gameObject, Point, Duration) ); yield return(new WaitForSeconds(Duration)); IsMovingInternal = false; }
public IEnumerator Spawn(EnemySpawn Spawn) { GameObject EnemyObject = Instantiate(Spawn.Prefab, Spawn.MovePath[0].position, Spawn.MovePath[0].rotation) as GameObject; EnemyHandler Enemy = EnemyObject.GetComponent <EnemyHandler>(); Master.Enemies.Add(Enemy); for (int i = 1; i < Spawn.MovePath.Length - 1; i++) { yield return(StartCoroutine( MovementCoroutines.MoveLerpWithRotaTo( EnemyObject, Spawn.MovePath[i].position, Spawn.MovePath[i].rotation, Spawn.LerpTime ) )); } Enemy.IsQueuedForDestruct = true; }
IEnumerator ZoomTo(Vector3 Point, float Duration, float ZoomOffset) { IsMovingInternal = true; StartCoroutine( MovementCoroutines.MoveLerpTo(gameObject, Point, Duration) ); StartCoroutine( MovementCoroutines.MoveLerpLocalTo( CameraObject, new Vector3(0, 0, ZoomMin + ZoomOffset), Duration ) ); yield return(new WaitForSeconds(Duration)); ZoomAxis = ZoomMin + ZoomOffset; ElevateAxis = transform.position.y; IsMovingInternal = false; }
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)); } }