Win and Lose screens overlap on lose condition

As the code currently stands the “win screen” will also be shown when the player loses, because EndGame(true) is also executed.

This can be easily fixed by putting the iteration over the AI controllers inside an else clause:


	// If player died -> player loses the game.
	APlayerController* PlayerController = Cast<APlayerController>(PawnKilled->GetController());
	if (PlayerController != nullptr)
	{
		EndGame(false);
	}
	else
	{
		// If all enemies are dead -> player wins the game.
		for (AShooterAIController* EnemyShooter : TActorRange<AShooterAIController>(GetWorld()))
		{
			if (!EnemyShooter->IsDead())
			{
				return;
			}
		}
		EndGame(true);
	}

Alternatively, it could also be fixed by returning after EndGame(false), but while that solution fixes the problem for now, it feels a bit more brittle.

	// If player died -> player loses the game.
	APlayerController* PlayerController = Cast<APlayerController>(PawnKilled->GetController());
	if (PlayerController != nullptr)
	{
		EndGame(false);
		return;
	}

	// If all enemies are dead -> player wins the game.
	for (AShooterAIController* EnemyShooter : TActorRange<AShooterAIController>(GetWorld()))
	{
		if (!EnemyShooter->IsDead())
		{
			return;
		}
	}
	EndGame(true);
1 Like

You could also simply put the EndGame(true); within the for loop.

Check if you put your else condition in AShooterPlayerController::GameHasEnded since when you add the if (bIsWinner) is false it should go to LoseScree part and add it to view

if (bIsWinner)
	{
		UUserWidget* WinScreen = CreateWidget(this, WinWidgetClass);
		if(WinScreen != nullptr)
		{
			WinScreen->AddToViewport();
		}
		GetWorldTimerManager().SetTimer(RestartTimerHandle, this, &APlayerController::RestartLevel, RestartDelay);
	}
	else
	{
		UUserWidget* LoseScreen = CreateWidget(this, LoseWidgetClass);
		if(LoseScreen != nullptr)
		{
			LoseScreen->AddToViewport();
		}
	}

Privacy & Terms