Пример #1
0
FAIRequestID AAIController::RequestPathAndMove(const FAIMoveRequest& MoveRequest, FPathFindingQuery& Query)
{
	FAIRequestID RequestID;

	UNavigationSystem* NavSys = UNavigationSystem::GetCurrent(GetWorld());
	if (NavSys)
	{
		FPathFindingResult PathResult = NavSys->FindPathSync(Query);
		if (PathResult.Result != ENavigationQueryResult::Error)
		{
			if (PathResult.IsSuccessful() && PathResult.Path.IsValid())
			{
				if (MoveRequest.IsUsingPathfinding())
				{
					if (MoveRequest.HasGoalActor())
					{
						PathResult.Path->SetGoalActorObservation(*MoveRequest.GetGoalActor(), 100.0f);
					}

					PathResult.Path->EnableRecalculationOnInvalidation(true);
				}

				RequestID = RequestMove(MoveRequest, PathResult.Path);
			}
		}
		else
		{
			UE_VLOG(this, LogAINavigation, Error, TEXT("Trying to find path to %s resulted in Error"), *GetNameSafe(MoveRequest.GetGoalActor()));
		}
	}

	return RequestID;
}
Пример #2
0
FAIRequestID AAIController::RequestPathAndMove(FPathFindingQuery& Query, AActor* Goal, float AcceptanceRadius, bool bStopOnOverlap, FCustomMoveSharedPtr CustomData)
{
	FAIRequestID RequestID;

	UNavigationSystem* NavSys = UNavigationSystem::GetCurrent(GetWorld());
	if (NavSys)
	{
		FPathFindingResult PathResult = NavSys->FindPathSync(Query);
		if (PathResult.Result != ENavigationQueryResult::Error)
		{
			if (PathResult.IsSuccessful() && PathResult.Path.IsValid())
			{
				if (Goal)
				{
					PathResult.Path->SetGoalActorObservation(*Goal, 100.0f);
				}

				PathResult.Path->EnableRecalculationOnInvalidation(true);
			}

			RequestID = RequestMove(PathResult.Path, Goal, AcceptanceRadius, bStopOnOverlap, CustomData);
		}
		else
		{
			UE_VLOG(this, LogBehaviorTree, Error, TEXT("Trying to find path to %s resulted in Error"), *GetNameSafe(Goal));
		}
	}

	return RequestID;
}
Пример #3
0
void PlayerUIDialog::ExecuteMoveOrMeleeAttack(RPG_Character* characterEntity)
{
  VASSERT(characterEntity);

#if defined (SUPPORTS_MULTITOUCH) && (HAVOK_VISION_RESTRUCTURING) && !defined(_VISION_ANDROID)

  // Wait 0.1 seconds in case player uses multi touch 
  if (m_wasPressedTime < 0.f)
  {
    m_wasPressedTime = Vision::GetTimer()->GetTime();
    return;
  }
  else if (Vision::GetTimer()->GetTime() - m_wasPressedTime < 0.1f)
  {
    return;
  }

#endif

//#ifdef _DEBUG
//  const VString msg = "Execute Primary Action.";
//  //Vision::Error.SystemMessage(msg.AsChar());
//  Vision::Message.Add(1, msg.AsChar());
//#endif

  const bool inputEdge = !m_wasDown_PlayerMoveOrMelee; // if primary action input is activated now, and wasn't previously, this is a press event.

  // Get the location of the player input and information about any hit object
  RPG_DamageableEntity* attackableEntity = NULL;
  hkvVec3 targetPoint(0.0f, 0.0f, 0.0f);
  GetFirstAttackableEntityUnderCursor(attackableEntity, targetPoint, characterEntity);

  if(attackableEntity)
  {
    // Hit an object
    if (inputEdge || attackableEntity != m_lastTargetEntity)
    {
      // Initial press event, or a continued press that slipped from one entity to another
      TryMeleeAttack(characterEntity, attackableEntity);
    }
    else
    {
      // Continued hold
      ContinueMeleeAttack(characterEntity, attackableEntity);
    }
  }
  else
  {
    // No object hit
    if (!characterEntity->IsAttacking())  // don't terminate an attack mid-swing
    {
      RequestMove(characterEntity, inputEdge);
    }
  }
  m_lastTargetEntity = attackableEntity;
  m_lastTargetPoint = targetPoint;
  m_wasDown_PlayerMoveOrMelee = true;
}
Пример #4
0
// deprecated
FAIRequestID AAIController::RequestMove(FNavPathSharedPtr Path, AActor* Goal, float AcceptanceRadius, bool bStopOnOverlap, FCustomMoveSharedPtr CustomData)
{
	FAIMoveRequest MoveReq(Goal);
	MoveReq.SetAcceptanceRadius(AcceptanceRadius);
	MoveReq.SetStopOnOverlap(bStopOnOverlap);
	MoveReq.SetUserData(CustomData);

	return RequestMove(MoveReq, Path);
}
Пример #5
0
// DEPRECATED FUNCTION SUPPORT
FAIRequestID AAIController::RequestPathAndMove(const FAIMoveRequest& MoveRequest, FPathFindingQuery& Query)
{
    FAIRequestID MoveId = FAIRequestID::InvalidRequest;

    FNavPathSharedPtr FoundPath;
    FindPathForMoveRequest(MoveRequest, Query, FoundPath);

    if (FoundPath.IsValid())
    {
        MoveId = RequestMove(MoveRequest, FoundPath);
    }

    return MoveId;
}
Пример #6
0
void PlayerUIDialog::ContinueMeleeAttack(RPG_Character* characterEntity, RPG_DamageableEntity * const targetEntity)
{
  VASSERT(characterEntity);
  const bool hitHighlightable = targetEntity->Components().GetComponentOfBaseType(V_RUNTIME_CLASS(RPG_HighlightableComponent));
  const bool hitAttackable = targetEntity->Components().GetComponentOfBaseType(V_RUNTIME_CLASS(RPG_AttackableComponent));
  //@debug: test log output
  //Vision::Error.Warning(hitEntity->GetMesh()->GetFilename());

  if (hitHighlightable || hitAttackable)
  {
    if (hitHighlightable)  //"(RPG) Highlightable"
    {
      //Vision::Error.Warning("(RPG) Highlightable");

#ifdef _DEBUG
      if (m_debugUI)
      {
        Vision::Message.DrawMessage3D("(RPG) Highlightable", targetEntity->GetPosition());
      }
#endif
    }

    if (hitAttackable)  //"(RPG) Attackable"
    {
      // if player's holding down primary action input on an existing attack action, this sets its continue flag to true.
      if (characterEntity->GetActionHandler().IsPerformingAction(AT_MeleeAttack))
      {
        characterEntity->GetActionHandler().SetActiveActionFlags(1);
      }

#ifdef _DEBUG
      if (m_debugUI)
      {
        Vision::Message.DrawMessage3D("(RPG) Attackable", targetEntity->GetPosition() + hkvVec3(0.0f, 0.0f, 16.0f)); // (@hack: offset a little to avoid overwriting other component messages)
      }
#endif
    }
  }
  else
  {
    if(!characterEntity->IsAttacking())
    {
      // fall back to the move if the entity we hit wasn't a highlightable or attackable.
      RequestMove(characterEntity, false);
    }
  }
}
Пример #7
0
EPathFollowingRequestResult::Type AAIController::MoveToActor(class AActor* Goal, float AcceptanceRadius, bool bStopOnOverlap, bool bUsePathfinding, bool bCanStrafe, TSubclassOf<UNavigationQueryFilter> FilterClass)
{
	SCOPE_CYCLE_COUNTER(STAT_MoveToActor);
	EPathFollowingRequestResult::Type Result = EPathFollowingRequestResult::Failed;

	UE_VLOG(this, LogNavigation, Log, TEXT("MoveToActor: Goal(%s) AcceptRadius(%.1f%s) bUsePathfinding(%d) bCanStrafe(%d)"),
		*GetNameSafe(Goal), AcceptanceRadius, bStopOnOverlap ? TEXT(" + agent") : TEXT(""), bUsePathfinding, bCanStrafe);

	if (Goal)
	{
		if (PathFollowingComponent && PathFollowingComponent->HasReached(Goal, AcceptanceRadius, !bStopOnOverlap))
		{
			UE_VLOG(this, LogNavigation, Log, TEXT("MoveToActor: already at goal!"));
			PathFollowingComponent->SetLastMoveAtGoal(true);

			OnMoveCompleted(0, EPathFollowingResult::Success);
			Result = EPathFollowingRequestResult::AlreadyAtGoal;
		}
		else 
		{
			FNavPathSharedPtr Path = FindPath(Goal, bUsePathfinding, UNavigationQueryFilter::GetQueryFilter(FilterClass));
			if (Path.IsValid())
			{
				bAllowStrafe = bCanStrafe;

				const uint32 RequestID = RequestMove(Path, Goal, AcceptanceRadius, bStopOnOverlap);
				Result = (RequestID != INVALID_MOVEREQUESTID) ? EPathFollowingRequestResult::RequestSuccessful : EPathFollowingRequestResult::Failed;
			}
		}
	}

	if (Result == EPathFollowingRequestResult::Failed)
	{
		if (PathFollowingComponent)
		{
			PathFollowingComponent->SetLastMoveAtGoal(false);
		}

		OnMoveCompleted(INVALID_MOVEREQUESTID, EPathFollowingResult::Invalid);
	}

	return Result;
}
Пример #8
0
void Player::Move()
{
	if(mPosX > 500.f || mPosX < -500.f)
	{
		mVecX *= -1;
	}
	if(mPosY > 500.f || mPosY < -500.f)
	{
		mVecY *= -1;
	}
	if(mPosZ > 500.f || mPosZ < -500.f)
	{
		mVecZ *= -1;
	}

	float newX = mPosX + mVecX;
	float newY = mPosY + mVecY;
	float newZ = mPosZ + mVecZ;

	RequestMove(newX, newY, newZ);
}
Пример #9
0
void PlayerUIDialog::TryMeleeAttack(RPG_Character* characterEntity, RPG_DamageableEntity * const targetEntity)
{ 
  VASSERT(characterEntity);

  const bool hitHighlightable = targetEntity->Components().GetComponentOfBaseType(V_RUNTIME_CLASS(RPG_HighlightableComponent));
  const bool hitAttackable = targetEntity->Components().GetComponentOfBaseType(V_RUNTIME_CLASS(RPG_AttackableComponent));
  //@debug: test log output
  //Vision::Error.Warning(hitEntity->GetMesh()->GetFilename());

  if (hitHighlightable || hitAttackable)
  {
    if (hitHighlightable)  //"(RPG) Highlightable"
    {
      //Vision::Error.Warning("(RPG) Highlightable");
    }

    if (hitAttackable)  //"(RPG) Attackable"
    {
      //Vision::Error.Warning("(RPG) Attackable");
      if(characterEntity->IsTargetWithinAttackRange(targetEntity))
      {
        characterEntity->GetActionHandler().PerformAction(AT_MeleeAttack, true, targetEntity, hkvVec3(0, 0, 0), 0);
      }
      else
      {
        characterEntity->GetActionHandler().PerformAction(AT_Move, true, targetEntity, hkvVec3(0, 0, 0), MF_AttackRange);
        characterEntity->GetActionHandler().PerformAction(AT_MeleeAttack, false, targetEntity);
      }
    }
  }
  else
  {
    // fall back to the move if the entity we hit wasn't a highlightable or attackable.
    if (!characterEntity->IsAttacking())
    {
      RequestMove(characterEntity, true);
    }
  }
}
Пример #10
0
EPathFollowingRequestResult::Type AAIController::MoveToLocation(const FVector& Dest, float AcceptanceRadius, bool bStopOnOverlap, bool bUsePathfinding, bool bProjectDestinationToNavigation, bool bCanStrafe, TSubclassOf<UNavigationQueryFilter> FilterClass)
{
	SCOPE_CYCLE_COUNTER(STAT_MoveToLocation);

	EPathFollowingRequestResult::Type Result = EPathFollowingRequestResult::Failed;
	bool bCanRequestMove = true;

	UE_VLOG(this, LogNavigation, Log, TEXT("MoveToLocation: Goal(%s) AcceptRadius(%.1f%s) bUsePathfinding(%d) bCanStrafe(%d)"),
		*Dest.ToString(), AcceptanceRadius, bStopOnOverlap ? TEXT(" + agent") : TEXT(""), bUsePathfinding, bCanStrafe);

	// Check input is valid
	if( Dest.ContainsNaN() )
	{
		UE_VLOG(this, LogNavigation, Error, TEXT("AAIController::MoveToLocation: Destination is not valid! Goal(%s) AcceptRadius(%.1f%s) bUsePathfinding(%d) bCanStrafe(%d)"),
			*Dest.ToString(), AcceptanceRadius, bStopOnOverlap ? TEXT(" + agent") : TEXT(""), bUsePathfinding, bCanStrafe);
		
		ensure( !Dest.ContainsNaN() );
		bCanRequestMove = false;
	}

	FVector GoalLocation = Dest;

	// fail if projection to navigation is required but it either failed or there's not navigation component
	if (bCanRequestMove && bProjectDestinationToNavigation && (NavComponent == NULL || !NavComponent->ProjectPointToNavigation(Dest, GoalLocation)))
	{
		UE_VLOG_LOCATION(this, Dest, 30.f, FLinearColor::Red, TEXT("AAIController::MoveToLocation failed to project destination location to navmesh"));
		bCanRequestMove = false;
	}

	if (bCanRequestMove && PathFollowingComponent && PathFollowingComponent->HasReached(GoalLocation, AcceptanceRadius, !bStopOnOverlap))
	{
		UE_VLOG(this, LogNavigation, Log, TEXT("MoveToLocation: already at goal!"));
		PathFollowingComponent->SetLastMoveAtGoal(true);

		OnMoveCompleted(0, EPathFollowingResult::Success);
		Result = EPathFollowingRequestResult::AlreadyAtGoal;
		bCanRequestMove = false;
	}

	if (bCanRequestMove)
	{
		FNavPathSharedPtr Path = FindPath(GoalLocation, bUsePathfinding, UNavigationQueryFilter::GetQueryFilter(FilterClass));
	if (Path.IsValid())
	{
		bAllowStrafe = bCanStrafe;

		const uint32 RequestID = RequestMove(Path, NULL, AcceptanceRadius, bStopOnOverlap);
			Result = (RequestID != INVALID_MOVEREQUESTID) ? EPathFollowingRequestResult::RequestSuccessful : EPathFollowingRequestResult::Failed;
		}
	}

	if (Result == EPathFollowingRequestResult::Failed)
	{
		if (PathFollowingComponent)
		{
			PathFollowingComponent->SetLastMoveAtGoal(false);
		}

		OnMoveCompleted(INVALID_MOVEREQUESTID, EPathFollowingResult::Invalid);
	}

	return Result;
}
Пример #11
0
FPathFollowingRequestResult AAIController::MoveTo(const FAIMoveRequest& MoveRequest, FNavPathSharedPtr* OutPath)
{
    // both MoveToActor and MoveToLocation can be called from blueprints/script and should keep only single movement request at the same time.
    // this function is entry point of all movement mechanics - do NOT abort in here, since movement may be handled by AITasks, which support stacking

    SCOPE_CYCLE_COUNTER(STAT_MoveTo);
    UE_VLOG(this, LogAINavigation, Log, TEXT("MoveTo: %s"), *MoveRequest.ToString());

    FPathFollowingRequestResult ResultData;
    ResultData.Code = EPathFollowingRequestResult::Failed;

    if (MoveRequest.IsValid() == false)
    {
        UE_VLOG(this, LogAINavigation, Error, TEXT("MoveTo request failed due MoveRequest not being valid. Most probably desireg Goal Actor not longer exists"), *MoveRequest.ToString());
        return ResultData;
    }

    if (PathFollowingComponent == nullptr)
    {
        UE_VLOG(this, LogAINavigation, Error, TEXT("MoveTo request failed due missing PathFollowingComponent"));
        return ResultData;
    }

    ensure(MoveRequest.GetNavigationFilter() || !DefaultNavigationFilterClass);

    bool bCanRequestMove = true;
    bool bAlreadyAtGoal = false;

    if (!MoveRequest.IsMoveToActorRequest())
    {
        if (MoveRequest.GetGoalLocation().ContainsNaN() || FAISystem::IsValidLocation(MoveRequest.GetGoalLocation()) == false)
        {
            UE_VLOG(this, LogAINavigation, Error, TEXT("AAIController::MoveTo: Destination is not valid! Goal(%s)"), TEXT_AI_LOCATION(MoveRequest.GetGoalLocation()));
            bCanRequestMove = false;
        }

        // fail if projection to navigation is required but it failed
        if (bCanRequestMove && MoveRequest.IsProjectingGoal())
        {
            UNavigationSystem* NavSys = UNavigationSystem::GetCurrent(GetWorld());
            const FNavAgentProperties& AgentProps = GetNavAgentPropertiesRef();
            FNavLocation ProjectedLocation;

            if (NavSys && !NavSys->ProjectPointToNavigation(MoveRequest.GetGoalLocation(), ProjectedLocation, INVALID_NAVEXTENT, &AgentProps))
            {
                UE_VLOG_LOCATION(this, LogAINavigation, Error, MoveRequest.GetGoalLocation(), 30.f, FColor::Red, TEXT("AAIController::MoveTo failed to project destination location to navmesh"));
                bCanRequestMove = false;
            }

            MoveRequest.UpdateGoalLocation(ProjectedLocation.Location);
        }

        bAlreadyAtGoal = bCanRequestMove && PathFollowingComponent->HasReached(MoveRequest);
    }
    else
    {
        bAlreadyAtGoal = bCanRequestMove && PathFollowingComponent->HasReached(MoveRequest);
    }

    if (bAlreadyAtGoal)
    {
        UE_VLOG(this, LogAINavigation, Log, TEXT("MoveTo: already at goal!"));
        ResultData.MoveId = PathFollowingComponent->RequestMoveWithImmediateFinish(EPathFollowingResult::Success);
        ResultData.Code = EPathFollowingRequestResult::AlreadyAtGoal;
    }
    else if (bCanRequestMove)
    {
        FPathFindingQuery PFQuery;

        const bool bValidQuery = BuildPathfindingQuery(MoveRequest, PFQuery);
        if (bValidQuery)
        {
            FNavPathSharedPtr Path;
            FindPathForMoveRequest(MoveRequest, PFQuery, Path);

            const FAIRequestID RequestID = Path.IsValid() ? RequestMove(MoveRequest, Path) : FAIRequestID::InvalidRequest;
            if (RequestID.IsValid())
            {
                bAllowStrafe = MoveRequest.CanStrafe();
                ResultData.MoveId = RequestID;
                ResultData.Code = EPathFollowingRequestResult::RequestSuccessful;

                if (OutPath)
                {
                    *OutPath = Path;
                }
            }
        }
    }

    if (ResultData.Code == EPathFollowingRequestResult::Failed)
    {
        ResultData.MoveId = PathFollowingComponent->RequestMoveWithImmediateFinish(EPathFollowingResult::Invalid);
    }

    return ResultData;
}