// Fill out your copyright notice in the Description page of Project Settings. #include "HitScanWeapon.h" #include "Blaster/Character/BlasterCharacter.h" #include "Blaster/Components/LagCompensationComponent.h" #include "Blaster/PlayerController/BlasterPlayerController.h" #include "Engine/SkeletalMeshSocket.h" #include "Kismet/GameplayStatics.h" #include "Particles/ParticleSystemComponent.h" void AHitScanWeapon::Fire(const FVector& HitTarget) { Super::Fire(HitTarget); APawn* OwnerPawn = Cast(GetOwner()); if (OwnerPawn == nullptr) return; AController* InstigatorController = OwnerPawn->GetController(); const USkeletalMeshSocket* MuzzleFlashSocket = GetWeaponMesh()->GetSocketByName("MuzzleFlash"); if (MuzzleFlashSocket) { FTransform SocketTransform = MuzzleFlashSocket->GetSocketTransform(GetWeaponMesh()); FVector Start = SocketTransform.GetLocation(); FHitResult FireHit; WeaponTraceHit(Start, HitTarget, FireHit); ABlasterCharacter* BlasterCharacter = Cast(FireHit.GetActor()); if (BlasterCharacter && InstigatorController) { bool bCauseAuthDamage = !bUseServerSideRewind || OwnerPawn->IsLocallyControlled(); if (HasAuthority() && bCauseAuthDamage) { const float DamageToCause = FireHit.BoneName.ToString() == FString("head") ? HeadShotDamage : Damage; UGameplayStatics::ApplyDamage( BlasterCharacter, DamageToCause, InstigatorController, this, UDamageType::StaticClass() ); } else if (!HasAuthority() && bUseServerSideRewind) { OwnerCharacter = OwnerCharacter == nullptr ? Cast(OwnerPawn) : OwnerCharacter; OwnerController = OwnerController == nullptr ? Cast(InstigatorController) : OwnerController; if (OwnerCharacter && OwnerController && OwnerCharacter->GetLagCompensation() && OwnerCharacter->IsLocallyControlled()) { OwnerCharacter->GetLagCompensation()->ServerScoreRequest( BlasterCharacter, Start, HitTarget, OwnerController->GetServerTime() - OwnerController->SingleTripTime, this ); } } } if (ImpactParticles) { UGameplayStatics::SpawnEmitterAtLocation( GetWorld(), ImpactParticles, FireHit.ImpactPoint, FireHit.ImpactNormal.Rotation() ); } if (HitSound) { UGameplayStatics::PlaySoundAtLocation( this, HitSound, FireHit.ImpactPoint ); } if (MuzzleFlash) { UGameplayStatics::SpawnEmitterAtLocation( GetWorld(), MuzzleFlash, SocketTransform ); } if (FireSound) { UGameplayStatics::PlaySoundAtLocation( this, FireSound, GetActorLocation() ); } } } void AHitScanWeapon::WeaponTraceHit(const FVector& TraceStart, const FVector& HitTarget, FHitResult& OutHit) { UWorld* World = GetWorld(); if (World) { FVector End = TraceStart + (HitTarget - TraceStart) * 1.25f; World->LineTraceSingleByChannel( OutHit, TraceStart, End, ECC_Visibility ); FVector BeamEnd = End; if (OutHit.bBlockingHit) { BeamEnd = OutHit.ImpactPoint; } else { OutHit.ImpactPoint = End; } if (BeamParticles) { UParticleSystemComponent* Beam = UGameplayStatics::SpawnEmitterAtLocation( World, BeamParticles, TraceStart, FRotator::ZeroRotator, true ); if (Beam) { Beam->SetVectorParameter(FName("Target"), BeamEnd); } } } }