private Task ChaseStart(State from) { PatrolState patrolState = (PatrolState)from; if (patrolState == null) { throw new InvalidOperationException("ChaseState can only be entered from PatrolState"); } ChaseState chaseState = stateMachine.GetCurrentState <ChaseState>(); if (chaseState == null) { throw new InvalidOperationException("ChaseStart can only be used with ChaseState"); } chaseState.ChaseTarget = patrolState.ChaseTarget; chaseState.ChaseColliderTarget = patrolState.ChaseColliderTarget; return(Task.FromResult(0)); }
private void ChaseUpdate() { Drone.Alerted = true; ChaseState chaseState = stateMachine.GetCurrentState <ChaseState>(); if (chaseState == null) { throw new InvalidOperationException("ChaseUpdate can only be used with ChaseState"); } if (chaseState.ChaseTarget == null) { // Stop chasing stateMachine.SwitchTo(PatrolState.Name); return; } IDestructible destructible = Utils.GetDestructible(chaseState.ChaseTarget); if (destructible == null) { throw new InvalidOperationException("ChaseTarget can only target IDestructibles"); } if (destructible.IsDead) { // Stop chasing stateMachine.SwitchTo(PatrolState.Name); return; } // Check if still overlapping bool withinRange = false; foreach (var collision in alertZoneTrigger.Collisions) { var targetCollider = collision.ColliderA.Entity != alertZoneTrigger.Entity ? collision.ColliderA : collision.ColliderB; if (targetCollider == chaseState.ChaseColliderTarget) { withinRange = true; break; } } if (!withinRange) { // Stop chasing stateMachine.SwitchTo(PatrolState.Name); return; } // Recalculate path to player? Vector3 actualTargetPos = chaseState.ChaseTarget.Transform.WorldMatrix.TranslationVector; var source = Entity.Transform.WorldMatrix.TranslationVector; var target = actualTargetPos; source.Y = 1.5f; target.Y = 1.5f; Vector3 aimDir = target - source; float distToTarget = aimDir.Length(); aimDir.Normalize(); var playerTargeted = Drone.UpdateHeadRotation(aimDir); // Process move step if (chaseState.MoveOperation != null) { if (!chaseState.MoveOperation.MoveNext()) { chaseState.MoveOperation = null; } } bool hasLineOfSight = CheckLineOfSight(Entity, chaseState.ChaseColliderTarget); if (hasLineOfSight) { if (distToTarget < 6.0f) { // No longer need to move, player is in line of sight, and drone is pretty close chaseState.MoveOperation = null; Drone.SetMovement(Vector3.Zero); } if (playerTargeted) { // Shoot the player Drone.Weapon?.TryShoot(chaseState.ChaseTarget); } } // Update path towards player when either not moving or // the current path would end up too far from the player float targetDistance = (actualTargetPos - chaseState.CurrentChaseTargetPosition).Length(); if (chaseState.MoveOperation == null || targetDistance > 1.0f) { chaseState.CurrentChaseTargetPosition = chaseState.ChaseTarget.Transform.WorldMatrix.TranslationVector; chaseState.MoveOperation = Move(chaseState.CurrentChaseTargetPosition); } }