void AShooterWeapon_Instant::ProcessInstantHit_Confirmed(const FHitResult& Impact, const FVector& Origin, const FVector& ShootDir, int32 RandomSeed, float ReticleSpread) { // handle damage if (ShouldDealDamage(Impact.GetActor())) { DealDamage(Impact, ShootDir); } // play FX on remote clients if (Role == ROLE_Authority) { HitNotify.Origin = Origin; HitNotify.RandomSeed = RandomSeed; HitNotify.ReticleSpread = ReticleSpread; } // play FX locally if (GetNetMode() != NM_DedicatedServer) { const FVector EndTrace = Origin + ShootDir * InstantConfig.WeaponRange; const FVector EndPoint = Impact.GetActor() ? Impact.ImpactPoint : EndTrace; SpawnTrailEffect(EndPoint); SpawnImpactEffects(Impact); } }
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); } } } } }
void ASWeaponInstant::SimulateInstantHit(const FVector& ImpactPoint) { const FVector MuzzleOrigin = GetMuzzleLocation(); /* Adjust direction based on desired crosshair impact point and muzzle location */ const FVector AimDir = (ImpactPoint - MuzzleOrigin).GetSafeNormal(); const FVector EndTrace = MuzzleOrigin + (AimDir * WeaponRange); const FHitResult Impact = WeaponTrace(MuzzleOrigin, EndTrace); if (Impact.bBlockingHit) { SpawnImpactEffects(Impact); SpawnTrailEffects(Impact.ImpactPoint); } else { SpawnTrailEffects(EndTrace); } }
void AShooterWeapon_Instant::SimulateInstantHit(const FVector& ShotOrigin, int32 RandomSeed, float ReticleSpread) { FRandomStream WeaponRandomStream(RandomSeed); const float ConeHalfAngle = FMath::DegreesToRadians(ReticleSpread * 0.5f); const FVector StartTrace = ShotOrigin; const FVector AimDir = GetAdjustedAim(); const FVector ShootDir = WeaponRandomStream.VRandCone(AimDir, ConeHalfAngle, ConeHalfAngle); const FVector EndTrace = StartTrace + ShootDir * InstantConfig.WeaponRange; FHitResult Impact = WeaponTrace(StartTrace, EndTrace); if (Impact.bBlockingHit) { SpawnImpactEffects(Impact); SpawnTrailEffect(Impact.ImpactPoint); } else { SpawnTrailEffect(EndTrace); } }