void ASWeaponInstant::FireWeapon() { const FVector AimDir = GetAdjustedAim(); const FVector CameraPos = GetCameraDamageStartLocation(AimDir); const FVector EndPos = CameraPos + (AimDir * WeaponRange); /* Check for impact by tracing from the camera position */ FHitResult Impact = WeaponTrace(CameraPos, EndPos); const FVector MuzzleOrigin = GetMuzzleLocation(); FVector AdjustedAimDir = AimDir; if (Impact.bBlockingHit) { /* Adjust the shoot direction to hit at the crosshair. */ AdjustedAimDir = (Impact.ImpactPoint - MuzzleOrigin).GetSafeNormal(); /* Re-trace with the new aim direction coming out of the weapon muzzle */ Impact = WeaponTrace(MuzzleOrigin, MuzzleOrigin + (AdjustedAimDir * WeaponRange)); } else { /* Use the maximum distance as the adjust direction */ Impact.ImpactPoint = FVector_NetQuantize(EndPos); } ProcessInstantHit(Impact, MuzzleOrigin, AdjustedAimDir); }
void AAmethystWeapon_Projectile::FireWeapon() { FVector ShootDir = GetAdjustedAim(); FVector Origin = GetMuzzleLocation(); // trace from camera to check what's under crosshair const float ProjectileAdjustRange = 10000.0f; const FVector StartTrace = GetCameraDamageStartLocation(ShootDir); const FVector EndTrace = StartTrace + ShootDir * ProjectileAdjustRange; FHitResult Impact = WeaponTrace(StartTrace, EndTrace); // and adjust directions to hit that actor if (Impact.bBlockingHit) { const FVector AdjustedDir = (Impact.ImpactPoint - Origin).SafeNormal(); bool bWeaponPenetration = false; const float DirectionDot = FVector::DotProduct(AdjustedDir, ShootDir); if (DirectionDot < 0.0f) { // shooting backwards = weapon is penetrating bWeaponPenetration = true; } else if (DirectionDot < 0.5f) { // check for weapon penetration if angle difference is big enough // raycast along weapon mesh to check if there's blocking hit FVector MuzzleStartTrace = Origin - GetMuzzleDirection() * 150.0f; FVector MuzzleEndTrace = Origin; FHitResult MuzzleImpact = WeaponTrace(MuzzleStartTrace, MuzzleEndTrace); if (MuzzleImpact.bBlockingHit) { bWeaponPenetration = true; } } if (bWeaponPenetration) { // spawn at crosshair position Origin = Impact.ImpactPoint - ShootDir * 10.0f; } else { // adjust direction to hit ShootDir = AdjustedDir; } } ServerFireProjectile(Origin, ShootDir); }
void ABaseWeapon::Instant_Fire() { const int32 RandomSeed = FMath::Rand(); FRandomStream WeaponRandomStream(RandomSeed); const float CurrentSpread = WeaponConfig.WeaponSpread; const float SpreadCone = FMath::DegreesToRadians(WeaponConfig.WeaponSpread * 0.5); const FVector AimDir = MyPawn->GetActorForwardVector(); const FVector StartTrace = MyPawn->GetActorLocation(); const FVector ShootDir = WeaponRandomStream.VRandCone(AimDir, SpreadCone, SpreadCone); FVector EndTrace; if (Target) { FVector TargetDir = (MyPawn->GetActorLocation() - Target->GetActorLocation()); TargetDir.Normalize(); FVector ShootDir2 = WeaponRandomStream.VRandCone(-TargetDir, SpreadCone, SpreadCone); EndTrace = StartTrace + ShootDir2 * WeaponConfig.WeaponRange; } else { EndTrace = StartTrace + ShootDir * WeaponConfig.WeaponRange; } const FHitResult Impact = WeaponTrace(StartTrace, EndTrace); SpawnParticle(EndTrace); HitActor = Cast<AActor>(Impact.GetActor()); //DrawDebugLine(GetWorld(), StartTrace, EndTrace, FColor::Red, false, 1.0f); if (HitActor) { Server_DealDamage(Impact, ShootDir, WeaponConfig); } }
//If we are firing trace the beam void AAssaultWeapon::Tick( float DeltaTime ) { Super::Tick( DeltaTime ); if(firing){ WeaponTrace(); } }
void ASWeaponInstant::FireWeapon() { const FVector AimDir = GetAdjustedAim(); const FVector StartPos = GetCameraDamageStartLocation(AimDir); const FVector EndPos = StartPos + (AimDir * WeaponRange); const FHitResult Impact = WeaponTrace(StartPos, EndPos); ProcessInstantHit(Impact, StartPos, AimDir); }
void AFP_FirstPersonCharacter::OnFire() { // Play a sound if there is one if (FireSound != NULL) { UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation()); } // try and play a firing animation if specified if(FireAnimation != NULL) { // Get the animation object for the arms mesh UAnimInstance* AnimInstance = Mesh1P->GetAnimInstance(); if(AnimInstance != NULL) { AnimInstance->Montage_Play(FireAnimation, 1.f); } } // Now send a trace from the end of our gun to see if we should hit anything APlayerController* PlayerController = Cast<APlayerController>(GetController()); // Calculate the direction of fire and the start location for trace FVector CamLoc; FRotator CamRot; PlayerController->GetPlayerViewPoint(CamLoc, CamRot); const FVector ShootDir = CamRot.Vector(); FVector StartTrace = FVector::ZeroVector; if (PlayerController) { FRotator UnusedRot; PlayerController->GetPlayerViewPoint(StartTrace, UnusedRot); // Adjust trace so there is nothing blocking the ray between the camera and the pawn, and calculate distance from adjusted start StartTrace = StartTrace + ShootDir * ((GetActorLocation() - StartTrace) | ShootDir); } // Calculate endpoint of trace const FVector EndTrace = StartTrace + ShootDir * WeaponRange; // Check for impact const FHitResult Impact = WeaponTrace(StartTrace, EndTrace); // Deal with impact AActor* DamagedActor = Impact.GetActor(); UPrimitiveComponent* DamagedComponent = Impact.GetComponent(); // If we hit an actor, with a component that is simulating physics, apply an impulse if ((DamagedActor != NULL) && (DamagedActor != this) && (DamagedComponent != NULL) && DamagedComponent->IsSimulatingPhysics()) { DamagedComponent->AddImpulseAtLocation(ShootDir*WeaponDamage, Impact.Location); } }
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 AWeapon::Instant_Fire() { const int32 RandomSeed = FMath::Rand(); FRandomStream WeaponRandomStream(RandomSeed); const float CurrentSpread = WeaponConfig.WeaponSpread; const float SpreadCone = FMath::DegreesToRadians(WeaponConfig.WeaponSpread * 0.5); const FVector AimDir = WeaponMesh->GetSocketRotation("MF").Vector(); const FVector StartTrace = WeaponMesh->GetSocketLocation("MF"); const FVector ShootDir = WeaponRandomStream.VRandCone(AimDir, SpreadCone, SpreadCone); const FVector EndTrace = StartTrace + ShootDir * WeaponConfig.WeaponRange; const FHitResult Impact = WeaponTrace(StartTrace, EndTrace); ProcessInstantHit(Impact, StartTrace, ShootDir, RandomSeed, CurrentSpread); }
void AShooterWeapon_Instant::FireWeapon() { const int32 RandomSeed = FMath::Rand(); FRandomStream WeaponRandomStream(RandomSeed); const float CurrentSpread = GetCurrentSpread(); const float ConeHalfAngle = FMath::DegreesToRadians(CurrentSpread * 0.5f); const FVector AimDir = GetAdjustedAim(); const FVector StartTrace = GetCameraDamageStartLocation(AimDir); const FVector ShootDir = WeaponRandomStream.VRandCone(AimDir, ConeHalfAngle, ConeHalfAngle); const FVector EndTrace = StartTrace + ShootDir * InstantConfig.WeaponRange; const FHitResult Impact = WeaponTrace(StartTrace, EndTrace); ProcessInstantHit(Impact, StartTrace, ShootDir, RandomSeed, CurrentSpread); CurrentFiringSpread = FMath::Min(InstantConfig.FiringSpreadMax, CurrentFiringSpread + InstantConfig.FiringSpreadIncrement); }
void ATraceWeapon::Attack() { Super::Attack(); FVector Start = GetActorLocation(); FVector Direction = Instigator->GetActorRotation().Vector(); FVector End = Start + Direction * Range; FHitResult Impact = WeaponTrace(Start, End); HitResult(Impact, Start, Direction); }
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); } }
void AShooterWeapon_Instant::SpawnImpactEffects(const FHitResult& Impact) { if (ImpactTemplate && Impact.bBlockingHit) { FHitResult UseImpact = Impact; // trace again to find component lost during replication if (!Impact.Component.IsValid()) { const FVector StartTrace = Impact.ImpactPoint + Impact.ImpactNormal * 10.0f; const FVector EndTrace = Impact.ImpactPoint - Impact.ImpactNormal * 10.0f; FHitResult Hit = WeaponTrace(StartTrace, EndTrace); UseImpact = Hit; } AShooterImpactEffect* EffectActor = GetWorld()->SpawnActorDeferred<AShooterImpactEffect>(ImpactTemplate, Impact.ImpactPoint, Impact.ImpactNormal.Rotation()); if (EffectActor) { EffectActor->SurfaceHit = UseImpact; UGameplayStatics::FinishSpawningActor(EffectActor, FTransform(Impact.ImpactNormal.Rotation(), Impact.ImpactPoint)); } } }