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; }
AActor* AGunLockGameMode::ChoosePlayerStart(AController* Player) { // Find a player start that is furthest from other players APawn* PawnToFit = DefaultPawnClass ? DefaultPawnClass->GetDefaultObject<APawn>() : NULL; APlayerStart* BestPlayerStart = NULL; float MaxPlayerDistance = 0.0f; for (int32 PlayerStartIndex = 0; PlayerStartIndex < PlayerStarts.Num(); ++PlayerStartIndex) { APlayerStart* PlayerStart = PlayerStarts[PlayerStartIndex]; if (PlayerStart != NULL) { // Always prefer the first "Play from Here" PlayerStart, if we find one while in PIE mode if (Cast<APlayerStartPIE>(PlayerStart) != NULL) return PlayerStart; // Find the minimum distance to other players float MinPlayerDistance = HALF_WORLD_MAX; FVector SpawnLocation = PlayerStart->GetActorLocation(); const FRotator SpawnRotation = PlayerStart->GetActorRotation(); for (FConstPlayerControllerIterator Iterator = GetWorld()->GetPlayerControllerIterator(); Iterator; ++Iterator) { APlayerController* PlayerController = *Iterator; if (Player != PlayerController && PlayerController->GetPawn()) { MinPlayerDistance = FMath::Min(MinPlayerDistance, (SpawnLocation - PlayerController->GetPawn()->GetActorLocation()).Size()); } } // Choose the spawn that is furtherest from all other players, to give them a fighting chance! if (MinPlayerDistance > MaxPlayerDistance) { MaxPlayerDistance = MinPlayerDistance; BestPlayerStart = PlayerStart; } } } //If we couldn't find any suitable spawns, pick a random one! if (BestPlayerStart == NULL && PlayerStarts.Num() > 0) { return PlayerStarts[FMath::RandRange(0, PlayerStarts.Num() - 1)]; } return BestPlayerStart; }
void ANinjaGameModeBase::BeginRound() { UWorld* World = GetWorld(); if (World) { ClearPlayerStartTags(); for (APlayerState* CurrState : GameState->PlayerArray) { ANinjaPlayerState* State = (ANinjaPlayerState*)CurrState; if (State) { APlayerController* Cont = (APlayerController*) State->GetOwner(); GEngine->AddOnScreenDebugMessage(-1, 1.5, FColor::Blue, FString::Printf(TEXT("%s"), *Cont->GetName())); if (State->GetChosenCharacter()) { GEngine->AddOnScreenDebugMessage(-1, 1.5, FColor::Red, FString::Printf(TEXT("%s - %s"), *Cont->GetName(), *State->GetChosenCharacter()->GetName())); } if (Cont) { ACharacter* Character = Cont->GetCharacter(); APlayerStart* PS = (APlayerStart*)ChoosePlayerStart(Cont); if (PS) { PS->PlayerStartTag = FName(TEXT("Taken")); if (Character) { Character->Destroy(); } FActorSpawnParameters Params; Params.Owner = Cont; ANinjaCharacter* SpawnedChar = World->SpawnActor<ANinjaCharacter>(State->GetChosenCharacter(), PS->GetActorLocation(), PS->GetActorRotation(), Params); if (SpawnedChar) { Cont->Possess(SpawnedChar); } } } } } } }