One of the Particle Effects is not replicated to the client

ImpactEffect is no replicated to the client

SWeapon.h



// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "SWeapon.generated.h"

class USkeletalMeshComponent;
class UDamageType;
class UCameraShake;

// Contains info of a single hit scan LineTrace
USTRUCT()
struct FHitScanTrace {
    GENERATED_BODY()

public:
    UPROPERTY()
    FVector_NetQuantize TraceTo;
    // FVector_NetQuantizeNormal -- to setup direction unit vector from -1 to 1

    UPROPERTY()
    TEnumAsByte<EPhysicalSurface> SurfaceType;


};

UCLASS()
class COOPGAME_API ASWeapon : public AActor
{
    GENERATED_BODY()

public:    
    // Sets default values for this actor's properties
    ASWeapon();

protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
    USkeletalMeshComponent* MeshComp;

    void PlayFireEffects(FVector TraceEndPoint);
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon")
    UParticleSystem* DefaultImpactEffect;

    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon")
    UParticleSystem* FleshImpactEffect;

    UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = "Weapon")
    FName MuzzleSocketName;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Weapon")
    UParticleSystem* TracerEffect;

    UFUNCTION(BlueprintCallable, Category = "Weapon")
    virtual void Fire();

    UFUNCTION(Server, Reliable, WithValidation)
    void ServerFire();


    UPROPERTY(ReplicatedUsing=OnRep_HitScanTrace)
    FHitScanTrace HitScanTrace;

    UFUNCTION()
    void OnRep_HitScanTrace();

    void  PlayImpactEffects(EPhysicalSurface SurfaceType, FVector ImpactLocation);

    virtual void GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const override;



SWeapon.cpp




// Fill out your copyright notice in the Description page of Project Settings.


#include "SWeapon.h"
#include "Components/SkeletalMeshComponent.h"
#include "DrawDebugHelpers.h"
#include "Kismet/GameplayStatics.h"
#include "Particles/ParticleSystem.h"
#include "Particles/ParticleSystemComponent.h"
#include "Engine/SkeletalMesh.h"
#include "PhysicalMaterials/PhysicalMaterial.h"
#include "CoopGame.h"
#include "SCharacter.h"
#include "Net/UnrealNetwork.h"

ASWeapon::ASWeapon()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    //PrimaryActorTick.bCanEverTick = true;

    MeshComp = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("MeshComp"));
    RootComponent = MeshComp;

    MuzzleSocketName = "MuzzleSocket";
    TracerTargetName = "BeamEnd";
//....


    bIsReloading = false;
    bAutoReloading = true;
    bCanFire = true;

    SetReplicates(true);
    NetUpdateFrequency = 75.0f;
    MinNetUpdateFrequency = 35.0f;
/....
}


void ASWeapon::Fire()
{
    if (Role < ROLE_Authority) {
        ServerFire();
    }

    UE_LOG(LogTemp, Warning, TEXT("FIRING!!!!"));
    ASCharacter* ActorOwner = Cast<ASCharacter>(GetOwner());

    if (!ActorOwner) {
        return;
    }

    if (ActorOwner->GetIsDead()) {
        ActorOwner->HanldeDeath();
    }

    if (CurrentAmmoInClip > 0 && bIsReloading == false) {
        FVector EyeLocation;
        FRotator EyeRotation;

        // Trace the world, from pawn eyes to crosshair location

        // this is for FPP(First Person Point)
        // default func by the UE4
        // created custom from GetActorEyesViewPoint(..) => GetPawnViewLocation() which we override in SCharacter.cpp file
        ActorOwner->GetActorEyesViewPoint(EyeLocation, EyeRotation);

        FVector ShootDirection = EyeRotation.Vector();
        FVector TraceEnd = EyeLocation + (ShootDirection * projectileLengthInCm);
        FVector TraceEndPoint = TraceEnd;
        UE_LOG(LogTemp, Warning, TEXT("Eye Location %a"), *EyeLocation.ToString()); // returns IDK what some address or so. 0x1312312312-23p
        UE_LOG(LogTemp, Warning, TEXT("Eye Rotation %s"), *EyeRotation.ToString());
        UE_LOG(LogTemp, Warning, TEXT("EyeRotation.Vector() %s"), *EyeRotation.Vector().ToString());
        UE_LOG(LogTemp, Warning, TEXT("TraceEnd %s"), *TraceEnd.ToString());

        FCollisionQueryParams CollQearyParams;
        CollQearyParams.AddIgnoredActor(ActorOwner); // do not collide with owner
        CollQearyParams.AddIgnoredActor(this); // do no collide with SWeapon
        CollQearyParams.bTraceComplex = true; // it will trace against each individual triangle of the mesh we hitting. IT GIVES us EXACT result (not just simple collision like CAPSULE or so, but something like head or leg)
        CollQearyParams.bReturnPhysicalMaterial = true; // to get the physical material of a mesh!!!

        FHitResult Hit;
        EPhysicalSurface SurfaceType = SurfaceType_Default;
        // ECC_Visibility - tells us that it will check collision with everything what is visible in scene
        // If sth block the linetrace then do some actions
        if (GetWorld()->LineTraceSingleByChannel(Hit, EyeLocation, TraceEnd, COLLISION_WEAPON, CollQearyParams)) {
            // Blocking hit! Process damage

            AActor* DamagedActor;
            DamagedActor = Hit.GetActor();

            SurfaceType = UPhysicalMaterial::DetermineSurfaceType(Hit.PhysMaterial.Get());

            PlayImpactEffects(SurfaceType, Hit.ImpactPoint);

            TraceEndPoint = Hit.ImpactPoint;

            float ActualDamage = BaseDamage;
            if (SurfaceType == SURFACE_FLESHVULNERABLE) {
                ActualDamage = HeadshotDamage; // damage for headshot;
            }

            UGameplayStatics::ApplyPointDamage(DamagedActor, ActualDamage, ShootDirection, Hit, ActorOwner->GetInstigatorController(), this, DamageType);
        }

        if (DebugWeaponDrawing > 0) {
            DrawDebugLine(GetWorld(), EyeLocation, TraceEnd, FColor::White, false, 1.0f, 0, 1.0f);
        }

        PlayFireEffects(TraceEndPoint);

        ActorOwner->AddCameraRecoil();
        DecreaseCurrentAmmo();
        UE_LOG(LogTemp, Warning, TEXT("Okay I can Start Fire"));

        if (Role == ROLE_Authority) {
            HitScanTrace.TraceTo = TraceEnd;
            HitScanTrace.SurfaceType = SurfaceType;
        }

        LastTimeFired = GetWorld()->TimeSeconds;
    }
    else if (RemainingAmmo > 0 && bAutoReloading == true && bIsReloading == false) {
        StartReloading();
        UE_LOG(LogTemp, Warning, TEXT("Start Relading From Fire"));
    }
}

void ASWeapon::OnRep_HitScanTrace()
{
    // Play CosmeticEffects
    PlayFireEffects(HitScanTrace.TraceTo);
    PlayImpactEffects(HitScanTrace.SurfaceType, HitScanTrace.TraceTo);

}

void ASWeapon::PlayImpactEffects(EPhysicalSurface SurfaceType, FVector ImpactPoint)
{
    UParticleSystem* SelectedEffect = nullptr;

    switch (SurfaceType)
    {
    case SURFACE_FLESHMATERIAL:
    case SURFACE_FLESHVULNERABLE:
        SelectedEffect = FleshImpactEffect;
        break;
    default:
        SelectedEffect = DefaultImpactEffect;
        break;
    }

    if (SelectedEffect) {

        FVector MuzzleLocation = MeshComp->GetSocketLocation(MuzzleSocketName);
        FVector ShootDirection = ImpactPoint - MuzzleLocation;
        ShootDirection.Normalize();


        UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), SelectedEffect, ImpactPoint, ShootDirection.Rotation());
        UE_LOG(LogTemp, Warning, TEXT("Hit.ImpactNormal.Rotation(): %s"), *ShootDirection.Rotation().ToString());
    }
}

void ASWeapon::StartFire()
{
    // LastTime e.g 1 and TimeBetweenShots = 0.1 = 1+0.1 = 1.1; GetWorld()->TimeSeconds = 1;

    UE_LOG(LogTemp, Warning, TEXT("void ASWeapon::StartFire()"));
    float FirstDelay = FMath::Max(LastTimeFired + TimeBetweenShots - GetWorld()->TimeSeconds, 0.0f);
    GetWorldTimerManager().SetTimer(TimerHandle_DelayBetweenShots, this, &ASWeapon::Fire, TimeBetweenShots, true, FirstDelay);
}

void ASWeapon::PlayFireEffects(FVector TraceEndPoint)
{
    if (MuzzleFlashEffect) {
        UGameplayStatics::SpawnEmitterAttached(MuzzleFlashEffect, MeshComp, MuzzleSocketName);
    }

    if (TracerEffect) {
        FVector MuzzleLocation = MeshComp->GetSocketLocation(MuzzleSocketName);
        UParticleSystemComponent* TracerComp = UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), TracerEffect, MuzzleLocation);

        if (TracerComp) {
            TracerComp->SetVectorParameter(TracerTargetName, TraceEndPoint);
        }
    }

    APawn* MyOwner = Cast<APawn>(GetOwner());
    if (MyOwner) {
        APlayerController* PC = Cast<APlayerController>(MyOwner->GetController());
        if (PC) {
            PC->ClientPlayCameraShake(FireCamShake);
        }
    }
}



ASCharacter.h



// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "SCharacter.generated.h"

class UCameraComponent;
class USpringArmComponent;
class ACustomProjectile;
class ASWeapon;
class USHealthComponent;

UCLASS()
class COOPGAME_API ASCharacter : public ACharacter
{
    GENERATED_BODY()

public:
    // Sets default values for this character's properties
    ASCharacter();

    UPROPERTY(Replicated)
    ASWeapon* CurrentWeapon;
    void StartFire();
    UFUNCTION()
    void OnHealthChanged(USHealthComponent* OwningHealthComponent, float Health, float HealthDelta, const class UDamageType* DamageType, class AController* InstigatedBy, AActor* DamageCauser);

    virtual void GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const override;


Ascharacter.cpp



void ASCharacter::BeginPlay()
{
    Super::BeginPlay();

    DefaultFOV = CameraComp ? CameraComp->FieldOfView : DefaultFOV;

    HealthComp->OnHealthChanged.AddDynamic(this, &ASCharacter::OnHealthChanged);

    // the same can be used like this: HasAuthority();
    if (HasAuthority()) {
        // Spawn Default Weapon
        FActorSpawnParameters SpawnParams;
        SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;

        CurrentWeapon = GetWorld()->SpawnActor<ASWeapon>(StarterWeapon, FVector::ZeroVector, FRotator::ZeroRotator, SpawnParams);
        if (CurrentWeapon) {
            CurrentWeapon->SetOwner(this);
            CurrentWeapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, WeaponSocketName);
        }
    }
}

void ASCharacter::StartFire()
{
    if (CurrentWeapon) {
        CurrentWeapon->StartFire();
    }
}

​​​​​​​
void ASCharacter::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
{
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);

    DOREPLIFETIME(ASCharacter, CurrentWeapon);
}


FIXED:
I have just completely rewritten the code, and It started to work as expected. IDK what was wrong;:confused::rolleyes:

Does it matter if I have Fire() function in public(scope), but UFUNCTION(Server, Reliable, WithValidation) ServerFire() in protected(scope)?