diff --git a/Content/Blueprints/Weapon/BP_AssaultRifle.uasset b/Content/Blueprints/Weapon/BP_AssaultRifle.uasset index e2d02ec..a1f9416 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/BP_GenadeLauncher.uasset b/Content/Blueprints/Weapon/BP_GenadeLauncher.uasset index eb5c836..2daf2f5 100644 Binary files a/Content/Blueprints/Weapon/BP_GenadeLauncher.uasset and b/Content/Blueprints/Weapon/BP_GenadeLauncher.uasset differ diff --git a/Content/Blueprints/Weapon/BP_RocketLauncher.uasset b/Content/Blueprints/Weapon/BP_RocketLauncher.uasset index 2de14b7..fa09271 100644 Binary files a/Content/Blueprints/Weapon/BP_RocketLauncher.uasset and b/Content/Blueprints/Weapon/BP_RocketLauncher.uasset differ diff --git a/Content/Blueprints/Weapon/BP_Shotgun.uasset b/Content/Blueprints/Weapon/BP_Shotgun.uasset index 960bd33..0b8f9c7 100644 Binary files a/Content/Blueprints/Weapon/BP_Shotgun.uasset and b/Content/Blueprints/Weapon/BP_Shotgun.uasset differ diff --git a/Content/Blueprints/Weapon/BP_Weapon.uasset b/Content/Blueprints/Weapon/BP_Weapon.uasset deleted file mode 100644 index c403c3b..0000000 Binary files a/Content/Blueprints/Weapon/BP_Weapon.uasset and /dev/null differ diff --git a/Content/Maps/BlasterMap.umap b/Content/Maps/BlasterMap.umap index 3ef44e3..ce5b2f6 100644 Binary files a/Content/Maps/BlasterMap.umap and b/Content/Maps/BlasterMap.umap differ diff --git a/Source/Blaster/Components/CombatComponent.cpp b/Source/Blaster/Components/CombatComponent.cpp index a078be5..f88c5dd 100644 --- a/Source/Blaster/Components/CombatComponent.cpp +++ b/Source/Blaster/Components/CombatComponent.cpp @@ -125,32 +125,34 @@ void UCombatComponent::Fire() void UCombatComponent::FireProjectileWeapon() { - if (PrimaryWeapon) + if (PrimaryWeapon && Character) { HitTarget = PrimaryWeapon->bUseScatter ? PrimaryWeapon->TraceEndWithScatter(HitTarget) : HitTarget; - LocalFire(HitTarget); + if (!Character->HasAuthority()) LocalFire(HitTarget); ServerFire(HitTarget); } } void UCombatComponent::FireHitScanWeapon() { - if (PrimaryWeapon) + if (PrimaryWeapon && Character) { HitTarget = PrimaryWeapon->bUseScatter ? PrimaryWeapon->TraceEndWithScatter(HitTarget) : HitTarget; - LocalFire(HitTarget); + if (!Character->HasAuthority()) LocalFire(HitTarget); ServerFire(HitTarget); } } void UCombatComponent::FireShotgun() { - if (AShotgun* Shotgun = Cast(PrimaryWeapon)) + AShotgun* Shotgun = Cast(PrimaryWeapon); + if (Shotgun && Character) { - TArray HitTargets; + TArray HitTargets; Shotgun->ShotgunTraceEndWithScatter(HitTarget, HitTargets); + if (!Character->HasAuthority()) ShotgunLocalFire(HitTargets); + ServerShotgunFire(HitTargets); } - } void UCombatComponent::StartFireTimer() @@ -186,16 +188,20 @@ void UCombatComponent::MulticastFire_Implementation(const FVector_NetQuantize& T LocalFire(TraceHitTarget); } +void UCombatComponent::ServerShotgunFire_Implementation(const TArray& TraceHitTargets) +{ + MulticastShotgunFire(TraceHitTargets); +} + +void UCombatComponent::MulticastShotgunFire_Implementation(const TArray& TraceHitTargets) +{ + if (Character && Character->IsLocallyControlled() && !Character->HasAuthority()) return; + ShotgunLocalFire(TraceHitTargets); +} + void UCombatComponent::LocalFire(const FVector_NetQuantize& TraceHitTarget) { if (PrimaryWeapon == nullptr) return; - if (Character && CombatState == ECombatState::ECS_Reloading && PrimaryWeapon->IsShotgun()) - { - Character->PlayFireMontage(bAiming); - PrimaryWeapon->Fire(TraceHitTarget); - CombatState = ECombatState::ECS_Unoccupied; - return; - } if (Character && CombatState == ECombatState::ECS_Unoccupied) { Character->PlayFireMontage(bAiming); @@ -203,6 +209,18 @@ void UCombatComponent::LocalFire(const FVector_NetQuantize& TraceHitTarget) } } +void UCombatComponent::ShotgunLocalFire(const TArray& TraceHitTargets) +{ + AShotgun* Shotgun = Cast(PrimaryWeapon); + if (Shotgun == nullptr || Character == nullptr) return; + if (CombatState == ECombatState::ECS_Reloading || CombatState == ECombatState::ECS_Unoccupied) + { + Character->PlayFireMontage(bAiming); + Shotgun->FireShotgun(TraceHitTargets); + CombatState = ECombatState::ECS_Unoccupied; + } +} + void UCombatComponent::EquipWeapon(AWeapon* WeaponToEquip) { if (Character == nullptr || WeaponToEquip == nullptr) return; diff --git a/Source/Blaster/Components/CombatComponent.h b/Source/Blaster/Components/CombatComponent.h index 8d64ddd..333057c 100644 --- a/Source/Blaster/Components/CombatComponent.h +++ b/Source/Blaster/Components/CombatComponent.h @@ -70,6 +70,12 @@ protected: UFUNCTION(NetMulticast, Reliable) void MulticastFire(const FVector_NetQuantize& TraceHitTarget); + UFUNCTION(Server, Reliable) + void ServerShotgunFire(const TArray& TraceHitTargets); + + UFUNCTION(NetMulticast, Reliable) + void MulticastShotgunFire(const TArray& TraceHitTargets); + void TraceUnderCrosshairs(FHitResult& TraceHitResult); void SetHUDCrosshairs(float DeltaTime); @@ -156,6 +162,7 @@ private: void StartFireTimer(); void FireTimerFinished(); void LocalFire(const FVector_NetQuantize& TraceHitTarget); + void ShotgunLocalFire(const TArray& TraceHitTargets); bool CanFire(); diff --git a/Source/Blaster/Weapon/Shotgun.cpp b/Source/Blaster/Weapon/Shotgun.cpp index f731459..bb788da 100644 --- a/Source/Blaster/Weapon/Shotgun.cpp +++ b/Source/Blaster/Weapon/Shotgun.cpp @@ -8,28 +8,29 @@ #include "Kismet/GameplayStatics.h" #include "Kismet/KismetMathLibrary.h" -void AShotgun::Fire(const FVector& HitTarget) +void AShotgun::FireShotgun(const TArray& HitTargets) { - AWeapon::Fire(HitTarget); - - APawn* OwnerPawn = Cast(GetOwner()); + AWeapon::Fire(FVector()); + const 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(); + const FTransform SocketTransform = MuzzleFlashSocket->GetSocketTransform(GetWeaponMesh()); + const FVector Start = SocketTransform.GetLocation(); + // Maps hit character to number of times hit TMap HitMap; - for (uint32 i = 0; i < NumberOfPellets; i++) + + for (FVector_NetQuantize HitTarget : HitTargets) { FHitResult FireHit; WeaponTraceHit(Start, HitTarget, FireHit); ABlasterCharacter* BlasterCharacter = Cast(FireHit.GetActor()); - if (BlasterCharacter && HasAuthority() && InstigatorController) + if (BlasterCharacter) { if (HitMap.Contains(BlasterCharacter)) { @@ -39,35 +40,34 @@ void AShotgun::Fire(const FVector& HitTarget) { HitMap.Emplace(BlasterCharacter, 1); } - } - if (ImpactParticles) - { - UGameplayStatics::SpawnEmitterAtLocation( - GetWorld(), - ImpactParticles, - FireHit.ImpactPoint, - FireHit.ImpactNormal.Rotation() - ); - } - if (HitSound) - { - UGameplayStatics::PlaySoundAtLocation( - this, - HitSound, - FireHit.ImpactPoint, - .5f, - FMath::FRandRange(-.5f, .5f) - ); + if (ImpactParticles) + { + UGameplayStatics::SpawnEmitterAtLocation( + GetWorld(), + ImpactParticles, + FireHit.ImpactPoint, + FireHit.ImpactNormal.Rotation() + ); + } + if (HitSound) + { + UGameplayStatics::PlaySoundAtLocation( + this, + HitSound, + FireHit.ImpactPoint, + .5f, + FMath::FRandRange(-.5f, .5f) + ); + } } } - for (auto HitPair : HitMap) { if (HitPair.Key && HasAuthority() && InstigatorController) { UGameplayStatics::ApplyDamage( - HitPair.Key, - Damage * HitPair.Value, + HitPair.Key, // Character that was hit + Damage * HitPair.Value, // Multiply Damage by number of times hit InstigatorController, this, UDamageType::StaticClass() @@ -77,7 +77,7 @@ void AShotgun::Fire(const FVector& HitTarget) } } -void AShotgun::ShotgunTraceEndWithScatter(const FVector& HitTarget, TArray& HitTargets) +void AShotgun::ShotgunTraceEndWithScatter(const FVector& HitTarget, TArray& HitTargets) { const USkeletalMeshSocket* MuzzleFlashSocket = GetWeaponMesh()->GetSocketByName("MuzzleFlash"); if (MuzzleFlashSocket == nullptr) return; @@ -94,7 +94,7 @@ void AShotgun::ShotgunTraceEndWithScatter(const FVector& HitTarget, TArray& HitTargets); + virtual void FireShotgun(const TArray& HitTargets); + void ShotgunTraceEndWithScatter(const FVector& HitTarget, TArray& HitTargets); private: