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; }
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; }
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; }
// 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); }
// 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; }
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); } } }
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; }
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); }
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); } } }
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; }
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; }