void AGameModeBase::RestartPlayerAtTransform(AController* NewPlayer, const FTransform& SpawnTransform) { if (NewPlayer == nullptr || NewPlayer->IsPendingKillPending()) { return; } UE_LOG(LogGameMode, Verbose, TEXT("RestartPlayerAtTransform %s"), (NewPlayer && NewPlayer->PlayerState) ? *NewPlayer->PlayerState->PlayerName : TEXT("Unknown")); if (MustSpectate(Cast<APlayerController>(NewPlayer))) { UE_LOG(LogGameMode, Verbose, TEXT("RestartPlayerAtTransform tried to restart a spectator-only player!")); return; } // Try to create a pawn to use of the default class for this player if (NewPlayer->GetPawn() == nullptr && GetDefaultPawnClassForController(NewPlayer) != nullptr) { NewPlayer->SetPawn(SpawnDefaultPawnAtTransform(NewPlayer, SpawnTransform)); } if (NewPlayer->GetPawn() == nullptr) { NewPlayer->FailedToSpawnPawn(); } else { FinishRestartPlayer(NewPlayer, SpawnTransform.GetRotation().Rotator()); } }
APawn* AGameModeBase::SpawnDefaultPawnAtTransform_Implementation(AController* NewPlayer, const FTransform& SpawnTransform) { FActorSpawnParameters SpawnInfo; SpawnInfo.Instigator = Instigator; SpawnInfo.ObjectFlags |= RF_Transient; // We never want to save default player pawns into a map UClass* PawnClass = GetDefaultPawnClassForController(NewPlayer); APawn* ResultPawn = GetWorld()->SpawnActor<APawn>(PawnClass, SpawnTransform, SpawnInfo); if (!ResultPawn) { UE_LOG(LogGameMode, Warning, TEXT("Couldn't spawn Pawn of type %s at %s"), *GetNameSafe(PawnClass), *SpawnTransform.ToHumanReadableString()); } return ResultPawn; }
AActor* AGameModeBase::ChoosePlayerStart_Implementation(AController* Player) { // Choose a player start APlayerStart* FoundPlayerStart = nullptr; UClass* PawnClass = GetDefaultPawnClassForController(Player); APawn* PawnToFit = PawnClass ? PawnClass->GetDefaultObject<APawn>() : nullptr; TArray<APlayerStart*> UnOccupiedStartPoints; TArray<APlayerStart*> OccupiedStartPoints; for (TActorIterator<APlayerStart> It(GetWorld()); It; ++It) { APlayerStart* PlayerStart = *It; if (PlayerStart->IsA<APlayerStartPIE>()) { // Always prefer the first "Play from Here" PlayerStart, if we find one while in PIE mode FoundPlayerStart = PlayerStart; break; } else { FVector ActorLocation = PlayerStart->GetActorLocation(); const FRotator ActorRotation = PlayerStart->GetActorRotation(); if (!GetWorld()->EncroachingBlockingGeometry(PawnToFit, ActorLocation, ActorRotation)) { UnOccupiedStartPoints.Add(PlayerStart); } else if (GetWorld()->FindTeleportSpot(PawnToFit, ActorLocation, ActorRotation)) { OccupiedStartPoints.Add(PlayerStart); } } } if (FoundPlayerStart == nullptr) { if (UnOccupiedStartPoints.Num() > 0) { FoundPlayerStart = UnOccupiedStartPoints[FMath::RandRange(0, UnOccupiedStartPoints.Num() - 1)]; } else if (OccupiedStartPoints.Num() > 0) { FoundPlayerStart = OccupiedStartPoints[FMath::RandRange(0, OccupiedStartPoints.Num() - 1)]; } } return FoundPlayerStart; }
void AGameModeBase::RestartPlayerAtPlayerStart(AController* NewPlayer, AActor* StartSpot) { if (NewPlayer == nullptr || NewPlayer->IsPendingKillPending()) { return; } if (!StartSpot) { UE_LOG(LogGameMode, Warning, TEXT("Player start not found, failed to RestartPlayerAtPlayerStart")); return; } UE_LOG(LogGameMode, Verbose, TEXT("RestartPlayerAtPlayerStart %s"), (NewPlayer && NewPlayer->PlayerState) ? *NewPlayer->PlayerState->PlayerName : TEXT("Unknown")); if (MustSpectate(Cast<APlayerController>(NewPlayer))) { UE_LOG(LogGameMode, Verbose, TEXT("RestartPlayerAtTransform tried to restart a spectator-only player!")); return; } // Try to create a pawn to use of the default class for this player if (NewPlayer->GetPawn() == nullptr && GetDefaultPawnClassForController(NewPlayer) != nullptr) { NewPlayer->SetPawn(SpawnDefaultPawnFor(NewPlayer, StartSpot)); } if (NewPlayer->GetPawn() == nullptr) { NewPlayer->FailedToSpawnPawn(); } else { // Tell the start spot it was used InitStartSpot(StartSpot, NewPlayer); FinishRestartPlayer(NewPlayer, StartSpot->GetActorRotation()); } }
void ASGameMode::RestartPlayer(class AController* NewPlayer) { /* Fallback to PlayerStart picking if team spawning is disabled or we're trying to spawn a bot. */ if (!bSpawnAtTeamPlayer || (NewPlayer->PlayerState && NewPlayer->PlayerState->bIsABot)) { Super::RestartPlayer(NewPlayer); return; } /* Look for a live player to spawn next to */ FVector SpawnOrigin = FVector::ZeroVector; FRotator StartRotation = FRotator::ZeroRotator; for (FConstPawnIterator It = GetWorld()->GetPawnIterator(); It; It++) { ASCharacter* MyCharacter = Cast<ASCharacter>(*It); if (MyCharacter && MyCharacter->IsAlive()) { /* Get the origin of the first player we can find */ SpawnOrigin = MyCharacter->GetActorLocation(); StartRotation = MyCharacter->GetActorRotation(); break; } } /* No player is alive (yet) - spawn using one of the PlayerStarts */ if (SpawnOrigin == FVector::ZeroVector) { Super::RestartPlayer(NewPlayer); return; } /* Get a point on the nav mesh near the other player */ FVector StartLocation = UNavigationSystem::GetRandomPointInRadius(NewPlayer, SpawnOrigin, 250.0f); // Try to create a pawn to use of the default class for this player if (NewPlayer->GetPawn() == nullptr && GetDefaultPawnClassForController(NewPlayer) != nullptr) { FActorSpawnParameters SpawnInfo; SpawnInfo.Instigator = Instigator; APawn* ResultPawn = GetWorld()->SpawnActor<APawn>(GetDefaultPawnClassForController(NewPlayer), StartLocation, StartRotation, SpawnInfo); if (ResultPawn == nullptr) { UE_LOG(LogGameMode, Warning, TEXT("Couldn't spawn Pawn of type %s at %s"), *GetNameSafe(DefaultPawnClass), &StartLocation); } NewPlayer->SetPawn(ResultPawn); } if (NewPlayer->GetPawn() == nullptr) { NewPlayer->FailedToSpawnPawn(); } else { NewPlayer->Possess(NewPlayer->GetPawn()); // If the Pawn is destroyed as part of possession we have to abort if (NewPlayer->GetPawn() == nullptr) { NewPlayer->FailedToSpawnPawn(); } else { // Set initial control rotation to player start's rotation NewPlayer->ClientSetRotation(NewPlayer->GetPawn()->GetActorRotation(), true); FRotator NewControllerRot = StartRotation; NewControllerRot.Roll = 0.f; NewPlayer->SetControlRotation(NewControllerRot); SetPlayerDefaults(NewPlayer->GetPawn()); } } }