#include "CogSamplePlayerController.h" #include "CogCommon.h" #include "CogSampleDefines.h" #include "CogSampleCharacter.h" #include "CogSampleLogCategories.h" #include "CogSampleTargetAcquisition.h" #include "Net/UnrealNetwork.h" #if ENABLE_COG #include "CogAbilityReplicator.h" #include "CogDebugDraw.h" #include "CogDebugReplicator.h" #include "CogEngineReplicator.h" #endif //ENABLE_COG //-------------------------------------------------------------------------------------------------------------------------- ACogSamplePlayerController::ACogSamplePlayerController() { } //-------------------------------------------------------------------------------------------------------------------------- void ACogSamplePlayerController::BeginPlay() { Super::BeginPlay(); #if ENABLE_COG ACogDebugReplicator::Spawn(this); ACogAbilityReplicator::Spawn(this); ACogEngineReplicator::Spawn(this); #endif //ENABLE_COG } //-------------------------------------------------------------------------------------------------------------------------- void ACogSamplePlayerController::OnPossess(APawn* InPawn) { COG_LOG_OBJECT(LogCogPossession, ELogVerbosity::Verbose, this, TEXT("")); ACogSampleCharacter* OldControlledCharacter = Cast(GetPawn()); //---------------------------------------------------------------------------------------------------------- // Case of pawn was possessed too early by the server before a join complete //---------------------------------------------------------------------------------------------------------- if (InPawn != nullptr && InPawn->Controller != nullptr) { COG_LOG_OBJECT(LogCogPossession, ELogVerbosity::Warning, this, TEXT("Asking %s to possess pawn %s more than once. Pawn will be restarted! Should call Unpossess first if possible."), *GetNameSafe(this), *GetNameSafe(InPawn)); InPawn->Controller->UnPossess(); } Super::OnPossess(InPawn); if (InPawn != nullptr) { //on server, the pawn are not possessed on begin play callback, need to do it here. if (IsLocalController()) { SetControlRotation(InPawn->GetActorRotation()); } } PossessedCharacter = Cast(InPawn); if (InitialPossessedCharacter == nullptr) { InitialPossessedCharacter = PossessedCharacter; } OnControlledCharacterChanged.Broadcast(this, PossessedCharacter.Get(), OldControlledCharacter); } //-------------------------------------------------------------------------------------------------------------------------- void ACogSamplePlayerController::AcknowledgePossession(APawn* NewPawn) { COG_LOG_OBJECT(LogCogPossession, ELogVerbosity::Verbose, this, TEXT("")); ACogSampleCharacter* OldControlledCharacter = Cast(AcknowledgedPawn); Super::AcknowledgePossession(NewPawn); if (InitialPossessedCharacter == nullptr) { InitialPossessedCharacter = Cast(NewPawn); } if (PossessedCharacter != nullptr) { PossessedCharacter->AcknowledgeUnpossession(); } PossessedCharacter = Cast(NewPawn); PossessedCharacter->AcknowledgePossession(this); OnControlledCharacterChanged.Broadcast(this, PossessedCharacter.Get(), OldControlledCharacter); } //-------------------------------------------------------------------------------------------------------------------------- void ACogSamplePlayerController::SetPossession(APawn* NewPawn) { if (NewPawn == nullptr || GetPawn() == NewPawn) { return; } //------------------------------------------------------------------------------------------- // Unplug the current controller so it doesn't conflict with the newly assigned controller //------------------------------------------------------------------------------------------- AController* OldController = NewPawn->GetController(); if (OldController != nullptr) { COG_LOG_OBJECT(LogCogPossession, ELogVerbosity::Verbose, this, TEXT("%s unpossess %s"), *GetNameSafe(OldController), *GetNameSafe(NewPawn)); OldController->UnPossess(); } //------------------------------------------------------------------------------------------- // We will need to replug the initial controller of the character we currently control //------------------------------------------------------------------------------------------- ACogSampleCharacter* OldCharacter = Cast(GetPawn()); //------------------------------------------------------------------------------------------- // Unpossess before possession to prevent a warning //------------------------------------------------------------------------------------------- COG_LOG_OBJECT(LogCogPossession, ELogVerbosity::Verbose, this, TEXT("%s unpossess %s"), *GetNameSafe(this), *GetNameSafe(GetPawn())); UnPossess(); COG_LOG_OBJECT(LogCogPossession, ELogVerbosity::Verbose, this, TEXT("%s possess %s"), *GetNameSafe(this), *GetNameSafe(NewPawn)); Possess(NewPawn); //------------------------------------------------------------------------------------------- // Replug the initial controller on the old character. For example, replug the initial // AI controller of an AI when the player finishes controlling it. This needs to be done // after the Possess call. //------------------------------------------------------------------------------------------- if (OldCharacter != nullptr && OldCharacter->InitialController != nullptr && OldCharacter->InitialController != this) { COG_LOG_OBJECT(LogCogPossession, ELogVerbosity::Verbose, this, TEXT("%s possess %s"), *GetNameSafe(OldCharacter->InitialController), *GetNameSafe(OldCharacter)); OldCharacter->InitialController->Possess(OldCharacter); } } //-------------------------------------------------------------------------------------------------------------------------- void ACogSamplePlayerController::ResetPossession() { SetPossession(InitialPossessedCharacter.Get()); } //-------------------------------------------------------------------------------------------------------------------------- void ACogSamplePlayerController::Tick(float DeltaSeconds) { Super::Tick(DeltaSeconds); TickTargeting(DeltaSeconds); } //-------------------------------------------------------------------------------------------------------------------------- void ACogSamplePlayerController::TickTargeting(float DeltaSeconds) { if (IsLocalController()) { if (TargetAcquisition == nullptr) { SetTarget(nullptr); return; } TArray TagretToIgnore; FCogSampleTargetAcquisitionResult Result; TargetAcquisition->FindBestTarget(this, TagretToIgnore, nullptr, true, FVector2D::ZeroVector, false, Result); SetTarget(Result.Target); } #if ENABLE_COG if (Target != nullptr && PossessedCharacter != nullptr) { FCogDebugDraw::Segment(LogCogTargetAcquisition, PossessedCharacter.Get(), PossessedCharacter->GetActorLocation(), Target->GetActorLocation(), FColor::White, false); } #endif //ENABLE_COG } //-------------------------------------------------------------------------------------------------------------------------- void ACogSamplePlayerController::SetTarget(AActor* Value) { if (Value == Target) { return; } AActor* OldTarget = Target.Get(); Target = Value; if (GetLocalRole() == ROLE_AutonomousProxy) { Server_SetTarget(Value); } OnTargetChanged.Broadcast(this, Target.Get(), OldTarget); } //-------------------------------------------------------------------------------------------------------------------------- void ACogSamplePlayerController::Server_SetTarget_Implementation(AActor* Value) { Target = Value; }