Announcement

Collapse
No announcement yet.

AAIController has OnPossess/OnUnpossess Events, AController has not

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

    [PROGRAMMING] AAIController has OnPossess/OnUnpossess Events, AController has not

    We have three classes:

    AController
    AAIController
    APlayerController
    where AController is the super class of the other two.

    However, only AAIController provides an event OnPossess/OnUnpossess.
    In my eyes this is a design flaw. as it should be for every Controller.

    Not to mention that OnPosess/OnUnpossess is the only event we can implement in Blueprint.

    Code:
     
    void AAIController::Possess(APawn* InPawn)
    {
    // don't even try possessing pending-kill pawns
    if (InPawn != nullptr && InPawn->IsPendingKill())
    {
    return;
    }
    Super::Possess(InPawn);
    if (GetPawn() == nullptr || InPawn == nullptr)
    {
    return;
    }
    // no point in doing navigation setup if pawn has no movement component
    const UPawnMovementComponent* MovementComp = InPawn->GetMovementComponent();
    if (MovementComp != NULL)
    {
    UpdateNavigationComponents();
    }
    if (PathFollowingComponent)
    {
    PathFollowingComponent->Initialize();
    }
    if (bWantsPlayerState)
    {
    ChangeState(NAME_Playing);
    }
    // a Pawn controlled by AI _requires_ a GameplayTasksComponent, so if Pawn
    // doesn't have one we need to create it
    if (CachedGameplayTasksComponent == nullptr)
    {
    UGameplayTasksComponent* GTComp = InPawn->FindComponentByClass<UGameplayTasksComponent>();
    if (GTComp == nullptr)
    {
    GTComp = NewObject<UGameplayTasksComponent>(InPawn, TEXT("GameplayTasksComponent"));
    GTComp->RegisterComponent();
    }
    CachedGameplayTasksComponent = GTComp;
    }
    if (CachedGameplayTasksComponent && !CachedGameplayTasksComponent->OnClaimedResourcesChange.Contains(this, GET_FUNCTION_NAME_CHECKED(AAIController, OnGameplayTaskResourcesClaimed)))
    {
    CachedGameplayTasksComponent->OnClaimedResourcesChange.AddDynamic(this, &AAIController::OnGameplayTaskResourcesClaimed);
    REDIRECT_OBJECT_TO_VLOG(CachedGameplayTasksComponent, this);
    }
    OnPossess(InPawn);
    }
    Code:
     
    void APlayerController::Possess(APawn* PawnToPossess)
    {
    if (!HasAuthority())
    {
    FMessageLog("PIE").Warning(FText::Format(
    LOCTEXT("PlayerControllerPossessAuthorityOnly", "Possess function should only be used by the network authority for {0}"),
    FText::FromName(GetFName())
    ));
    UE_LOG(LogPlayerController, Warning, TEXT("Trying to possess %s without network authority! Request will be ignored."), *GetNameSafe(PawnToPossess));
    return;
    }
    if ( PawnToPossess != NULL &&
    (PlayerState == NULL || !PlayerState->bOnlySpectator) )
    {
    if (GetPawn() && GetPawn() != PawnToPossess)
    {
    UnPossess();
    }
    if (PawnToPossess->Controller != NULL)
    {
    PawnToPossess->Controller->UnPossess();
    }
    PawnToPossess->PossessedBy(this);
    // update rotation to match possessed pawn's rotation
    SetControlRotation( PawnToPossess->GetActorRotation() );
    SetPawn(PawnToPossess);
    check(GetPawn() != NULL);
    if (GetPawn() && GetPawn()->PrimaryActorTick.bStartWithTickEnabled)
    {
    GetPawn()->SetActorTickEnabled(true);
    }
    INetworkPredictionInterface* NetworkPredictionInterface = GetPawn() ? Cast<INetworkPredictionInterface>(GetPawn()->GetMovementComponent()) : NULL;
    if (NetworkPredictionInterface)
    {
    NetworkPredictionInterface->ResetPredictionData_Server();
    }
    AcknowledgedPawn = NULL;
    // Local PCs will have the Restart() triggered right away in ClientRestart (via PawnClientRestart()), but the server should call Restart() locally for remote PCs.
    // We're really just trying to avoid calling Restart() multiple times.
    if (!IsLocalPlayerController())
    {
    GetPawn()->Restart();
    }
    ClientRestart(GetPawn());
    ChangeState( NAME_Playing );
    if (bAutoManageActiveCameraTarget)
    {
    AutoManageActiveCameraTarget(GetPawn());
    ResetCameraMode();
    }
    UpdateNavigationComponents();
    }
    }
    Code:
     
    void AController::Possess(APawn* InPawn)
    {
    if (!HasAuthority())
    {
    FMessageLog("PIE").Warning(FText::Format(
    LOCTEXT("ControllerPossessAuthorityOnly", "Possess function should only be used by the network authority for {0}"),
    FText::FromName(GetFName())
    ));
    return;
    }
    REDIRECT_OBJECT_TO_VLOG(InPawn, this);
    if (InPawn != NULL)
    {
    if (GetPawn() && GetPawn() != InPawn)
    {
    UnPossess();
    }
    if (InPawn->Controller != NULL)
    {
    InPawn->Controller->UnPossess();
    }
    InPawn->PossessedBy(this);
    SetPawn(InPawn);
    // update rotation to match possessed pawn's rotation
    SetControlRotation( Pawn->GetActorRotation() );
    Pawn->Restart();
    }
    }
    Possess() may be virtual, but it isn't BlueprintNative or BlueprintImplementable.
    (I could create a Base C++ Class for my own Controller, but I use BP as a prototype and I would like to have all features I would have in the future, too)
Working...
X