void ASWeaponInstant::SimulateInstantHit(const FVector& Origin)
{
	const FVector StartTrace = Origin;
	const FVector AimDir = GetAdjustedAim();
	const FVector EndTrace = StartTrace + (AimDir * WeaponRange);

 	const FHitResult Impact = WeaponTrace(StartTrace, EndTrace);
	if (Impact.bBlockingHit)
	{
		SpawnImpactEffects(Impact);
		SpawnTrailEffects(Impact.ImpactPoint);
	}
	else
	{
		SpawnTrailEffects(EndTrace);
	}

	// Do not spawn near-hit if we actually hit a pawn
	if (Impact.GetActor() && Impact.GetActor()->IsA(ASCharacter::StaticClass()))
	{
		return;
	}

	for (FConstPawnIterator It = GetWorld()->GetPawnIterator(); It; It++)
	{
		// Find a locally controlled pawn that is not the instigator of the hit.
		ASCharacter* OtherPawn = Cast<ASCharacter>(*It);
		if (OtherPawn && OtherPawn != GetPawnOwner() && OtherPawn->IsLocallyControlled())
		{
			// Calculate shortest distance to point. (using the estimated eye height)
			const float DistanceToPawn = FVector::CrossProduct(AimDir, OtherPawn->GetActorLocation() - Origin).Size();

			/* Owner can be lost before client gets to simulate the hit. */
			ASCharacter* P = GetPawnOwner();
			if (P)
			{
				FVector LookAt = (OtherPawn->GetActorLocation() - GetPawnOwner()->GetActorLocation());
				LookAt.Normalize();
				float LookDot = FVector::DotProduct(AimDir, LookAt);

				if (DistanceToPawn < NearHitMaxDistance && LookDot > 0)
				{
					// TODO: Play at nearest "almost" hit location.
					const FVector SoundLocation = Origin + (AimDir * DistanceToPawn);

					// Volume is based on distance to missed shot
					float Volume = FMath::Clamp(1 - (DistanceToPawn / NearHitMaxDistance), 0.1f, 1.0f);

					UGameplayStatics::PlaySoundAtLocation(this, NearHitSound, /*SoundLocation*/ OtherPawn->GetActorLocation(), Volume);
				}
			}
		}
	}
}
Ejemplo n.º 2
0
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());
		}
	}
}