diff --git a/Content/Blueprints/Weapon/BP_AssaultRifle.uasset b/Content/Blueprints/Weapon/BP_AssaultRifle.uasset index a1f9416..fcd2d8b 100644 Binary files a/Content/Blueprints/Weapon/BP_AssaultRifle.uasset and b/Content/Blueprints/Weapon/BP_AssaultRifle.uasset differ diff --git a/Content/Blueprints/Weapon/Projectiles/BP_ServerSideRewindProjectile.uasset b/Content/Blueprints/Weapon/Projectiles/BP_ServerSideRewindProjectile.uasset new file mode 100644 index 0000000..13ee9d6 Binary files /dev/null and b/Content/Blueprints/Weapon/Projectiles/BP_ServerSideRewindProjectile.uasset differ diff --git a/Source/Blaster/Weapon/Projectile.h b/Source/Blaster/Weapon/Projectile.h index db0da77..71869d6 100644 --- a/Source/Blaster/Weapon/Projectile.h +++ b/Source/Blaster/Weapon/Projectile.h @@ -23,6 +23,8 @@ public: UPROPERTY(EditAnywhere) float InitialSpeed = 15000; + + float Damage = 20.f; protected: virtual void BeginPlay() override; @@ -35,9 +37,6 @@ protected: virtual void OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit); virtual void Destroyed() override; - UPROPERTY(EditAnywhere) - float Damage = 20.f; - UPROPERTY(EditAnywhere) class UParticleSystem* ImpactParticles; diff --git a/Source/Blaster/Weapon/ProjectileWeapon.cpp b/Source/Blaster/Weapon/ProjectileWeapon.cpp index 1488240..0f508fa 100644 --- a/Source/Blaster/Weapon/ProjectileWeapon.cpp +++ b/Source/Blaster/Weapon/ProjectileWeapon.cpp @@ -10,32 +10,61 @@ void AProjectileWeapon::Fire(const FVector& HitTarget) { Super::Fire(HitTarget); - if (!HasAuthority()) return; - APawn* InstigatorPawn = Cast(GetOwner()); const USkeletalMeshSocket* MuzzleFlashSocket = GetWeaponMesh()->GetSocketByName(FName("MuzzleFlash")); - if (MuzzleFlashSocket) + UWorld* World = GetWorld(); + if (MuzzleFlashSocket && World) { FTransform SocketTransform = MuzzleFlashSocket->GetSocketTransform(GetWeaponMesh()); // From muzzle flash socket to hit location from TraceUnderCrosshairs FVector ToTarget = HitTarget - SocketTransform.GetLocation(); FRotator TargetRotation = ToTarget.Rotation(); - - if (ProjectileClass && InstigatorPawn) - { - FActorSpawnParameters SpawnParams; - SpawnParams.Owner = GetOwner(); - SpawnParams.Instigator = InstigatorPawn; - UWorld* World = GetWorld(); - if (World) + FActorSpawnParameters SpawnParams; + SpawnParams.Owner = GetOwner(); + SpawnParams.Instigator = InstigatorPawn; + + AProjectile* SpawnedProjectile = nullptr; + if (bUseServerSideRewind) + { + if (InstigatorPawn->HasAuthority()) // Server { - World->SpawnActor( - ProjectileClass, - SocketTransform.GetLocation(), - TargetRotation, - SpawnParams - ); + if (InstigatorPawn->IsLocallyControlled()) // Server, host - use replicated projectile + { + SpawnedProjectile = World->SpawnActor(ProjectileClass, SocketTransform.GetLocation(), TargetRotation, SpawnParams); + SpawnedProjectile->bUseServerSideRewind = false; + SpawnedProjectile->Damage = Damage; + } + else // Server, not locally controlled - spawn non-replicated projectile, no SSR + { + SpawnedProjectile = World->SpawnActor(ServerSideRewindProjectileClass, SocketTransform.GetLocation(), TargetRotation, SpawnParams); + SpawnedProjectile->bUseServerSideRewind = false; + } + } + else // Client, using SSR + { + if (InstigatorPawn->IsLocallyControlled()) // Client, locally controlled - spawn non-replicated projectile, use SSR + { + SpawnedProjectile = World->SpawnActor(ServerSideRewindProjectileClass, SocketTransform.GetLocation(), TargetRotation, SpawnParams); + SpawnedProjectile->bUseServerSideRewind = true; + SpawnedProjectile->TraceStart = SocketTransform.GetLocation(); + SpawnedProjectile->InitialVelocity= SpawnedProjectile->GetActorForwardVector() * SpawnedProjectile->InitialSpeed; + SpawnedProjectile->Damage = Damage; + } + else // Client, not locally controlled - spawn non-replicated projectile, no SSR + { + SpawnedProjectile = World->SpawnActor(ServerSideRewindProjectileClass, SocketTransform.GetLocation(), TargetRotation, SpawnParams); + SpawnedProjectile->bUseServerSideRewind = false; + } + } + } + else // Weapon not using SSR + { + if (InstigatorPawn->HasAuthority()) + { + SpawnedProjectile = World->SpawnActor(ProjectileClass, SocketTransform.GetLocation(), TargetRotation, SpawnParams); + SpawnedProjectile->bUseServerSideRewind = false; + SpawnedProjectile->Damage = Damage; } } } diff --git a/Source/Blaster/Weapon/ProjectileWeapon.h b/Source/Blaster/Weapon/ProjectileWeapon.h index 7437f09..c1bbb70 100644 --- a/Source/Blaster/Weapon/ProjectileWeapon.h +++ b/Source/Blaster/Weapon/ProjectileWeapon.h @@ -20,4 +20,7 @@ private: UPROPERTY(EditAnywhere) TSubclassOf ProjectileClass; + UPROPERTY(EditAnywhere) + TSubclassOf ServerSideRewindProjectileClass; + };