// Fill out your copyright notice in the Description page of Project Settings. #include "CombatComponent.h" #include "Blaster/Character/BlasterCharacter.h" #include "Blaster/PlayerController/BlasterPlayerController.h" #include "Blaster/Weapon/Shotgun.h" #include "Blaster/Weapon/Weapon.h" #include "Camera/CameraComponent.h" #include "Engine/SkeletalMeshSocket.h" #include "GameFramework/CharacterMovementComponent.h" #include "Kismet/GameplayStatics.h" #include "Net/UnrealNetwork.h" UCombatComponent::UCombatComponent() { PrimaryComponentTick.bCanEverTick = true; BaseWalkSpeed = 600.f; AimWalkSpeed = 350.f; } void UCombatComponent::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); DOREPLIFETIME(UCombatComponent, PrimaryWeapon); DOREPLIFETIME(UCombatComponent, SecondaryWeapon); DOREPLIFETIME(UCombatComponent, bAiming); DOREPLIFETIME_CONDITION(UCombatComponent, CarriedAmmo, COND_OwnerOnly); DOREPLIFETIME(UCombatComponent, CombatState); DOREPLIFETIME(UCombatComponent, Grenades); } void UCombatComponent::PickupAmmo(EWeaponType WeaponType, int32 AmmoAmount) { if (CarriedAmmoMap.Contains(WeaponType)) { CarriedAmmoMap[WeaponType] = FMath::Clamp(CarriedAmmoMap[WeaponType] + AmmoAmount, 0, MaxCarriedAmmo); UpdateCarriedAmmo(); } if (PrimaryWeapon && PrimaryWeapon->IsEmpty() && PrimaryWeapon->GetWeaponType() == WeaponType) { Reload(); } } void UCombatComponent::BeginPlay() { Super::BeginPlay(); if (Character) { Character->GetCharacterMovement()->MaxWalkSpeed = BaseWalkSpeed; if (Character->GetFollowCamera()) { DefaultFOV = Character->GetFollowCamera()->FieldOfView; CurrentFOV = DefaultFOV; } if (Character->HasAuthority()) { InitializeCarriedAmmo(); } } } void UCombatComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) { Super::TickComponent(DeltaTime, TickType, ThisTickFunction); if (Character && Character->IsLocallyControlled()) { FHitResult HitResult; TraceUnderCrosshairs(HitResult); HitTarget = HitResult.ImpactPoint; SetHUDCrosshairs(DeltaTime); InterpFOV(DeltaTime); } } void UCombatComponent::FireButtonPressed(bool bPressed) { bFireButtonPressed = bPressed; if (bFireButtonPressed && PrimaryWeapon) { Fire(); } } void UCombatComponent::ShotgunShellReload() { if (Character && Character->HasAuthority()) { UpdateShotgunAmmoValues(); } } void UCombatComponent::Fire() { if (CanFire()) { bCanFire = false; if (PrimaryWeapon) { CrosshairShootingFactor = .75f; switch (PrimaryWeapon->FireType) { case EFireType::EFT_HitScan: FireHitScanWeapon(); break; case EFireType::EFT_Projectile: FireProjectileWeapon(); break; case EFireType::EFT_Shotgun: FireShotgun(); break; } } StartFireTimer(); } } void UCombatComponent::FireProjectileWeapon() { if (PrimaryWeapon && Character) { HitTarget = PrimaryWeapon->bUseScatter ? PrimaryWeapon->TraceEndWithScatter(HitTarget) : HitTarget; if (!Character->HasAuthority()) LocalFire(HitTarget); ServerFire(HitTarget); } } void UCombatComponent::FireHitScanWeapon() { if (PrimaryWeapon && Character) { HitTarget = PrimaryWeapon->bUseScatter ? PrimaryWeapon->TraceEndWithScatter(HitTarget) : HitTarget; if (!Character->HasAuthority()) LocalFire(HitTarget); ServerFire(HitTarget); } } void UCombatComponent::FireShotgun() { AShotgun* Shotgun = Cast(PrimaryWeapon); if (Shotgun && Character) { TArray HitTargets; Shotgun->ShotgunTraceEndWithScatter(HitTarget, HitTargets); if (!Character->HasAuthority()) ShotgunLocalFire(HitTargets); ServerShotgunFire(HitTargets); } } void UCombatComponent::StartFireTimer() { if (PrimaryWeapon == nullptr || Character == nullptr) return; Character->GetWorldTimerManager().SetTimer( FireTimer, this, &UCombatComponent::FireTimerFinished, PrimaryWeapon->FireDelay ); } void UCombatComponent::FireTimerFinished() { if (PrimaryWeapon == nullptr) return; bCanFire = true; if (bFireButtonPressed && PrimaryWeapon->bAutomatic) { Fire(); } ReloadEmptyWeapon(); } void UCombatComponent::ServerFire_Implementation(const FVector_NetQuantize& TraceHitTarget) { MulticastFire(TraceHitTarget); } void UCombatComponent::MulticastFire_Implementation(const FVector_NetQuantize& TraceHitTarget) { if (Character && Character->IsLocallyControlled() && !Character->HasAuthority()) return; 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_Unoccupied) { Character->PlayFireMontage(bAiming); PrimaryWeapon->Fire(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; if (CombatState != ECombatState::ECS_Unoccupied) return; if (PrimaryWeapon != nullptr && SecondaryWeapon == nullptr) { EquipSecondaryWeapon(WeaponToEquip); } else { EquipPrimaryWeapon(WeaponToEquip); } Character->GetCharacterMovement()->bOrientRotationToMovement = false; Character->bUseControllerRotationYaw = true; } void UCombatComponent::SwapWeapons() { if (CombatState != ECombatState::ECS_Unoccupied) return; AWeapon* TempWeapon = PrimaryWeapon; PrimaryWeapon = SecondaryWeapon; SecondaryWeapon = TempWeapon; PrimaryWeapon->SetWeaponState(EWeaponState::EWS_Equipped); AttachActorToRightHand(PrimaryWeapon); PrimaryWeapon->SetHUDAmmo(); UpdateCarriedAmmo(); PlayEquipWeaponSound(PrimaryWeapon); SecondaryWeapon->SetWeaponState(EWeaponState::EWS_EquippedSecondary); AttachActorToBackpack(SecondaryWeapon); } bool UCombatComponent::ShouldSwapWeapons() { return PrimaryWeapon != nullptr && SecondaryWeapon != nullptr; } void UCombatComponent::EquipPrimaryWeapon(AWeapon* WeaponToEquip) { if (WeaponToEquip == nullptr) return; DropPrimaryWeapon(); PrimaryWeapon = WeaponToEquip; PrimaryWeapon->SetWeaponState(EWeaponState::EWS_Equipped); AttachActorToRightHand(PrimaryWeapon); PrimaryWeapon->SetOwner(Character); PrimaryWeapon->SetHUDAmmo(); UpdateCarriedAmmo(); PlayEquipWeaponSound(PrimaryWeapon); ReloadEmptyWeapon(); } void UCombatComponent::EquipSecondaryWeapon(AWeapon* WeaponToEquip) { if (WeaponToEquip == nullptr) return; SecondaryWeapon = WeaponToEquip; SecondaryWeapon->SetWeaponState(EWeaponState::EWS_EquippedSecondary); AttachActorToBackpack(WeaponToEquip); PlayEquipWeaponSound(SecondaryWeapon); SecondaryWeapon->SetOwner(Character); } void UCombatComponent::OnRep_PrimaryWeapon() { if (PrimaryWeapon && Character) { PrimaryWeapon->SetWeaponState(EWeaponState::EWS_Equipped); AttachActorToRightHand(PrimaryWeapon); Character->GetCharacterMovement()->bOrientRotationToMovement = false; Character->bUseControllerRotationYaw = true; PlayEquipWeaponSound(PrimaryWeapon); PrimaryWeapon->SetHUDAmmo(); } } void UCombatComponent::OnRep_SecondaryWeapon() { if (SecondaryWeapon && Character) { SecondaryWeapon->SetWeaponState(EWeaponState::EWS_EquippedSecondary); AttachActorToBackpack(SecondaryWeapon); PlayEquipWeaponSound(SecondaryWeapon); } } void UCombatComponent::DropPrimaryWeapon() { if (PrimaryWeapon) { PrimaryWeapon->Dropped(); } } void UCombatComponent::AttachActorToRightHand(AActor* ActorToAttach) { if (Character == nullptr || Character->GetMesh() == nullptr|| ActorToAttach == nullptr) return; const USkeletalMeshSocket* HandSocket = Character->GetMesh()->GetSocketByName(FName("RightHandSocket")); if (HandSocket) { HandSocket->AttachActor(ActorToAttach, Character->GetMesh()); } } void UCombatComponent::AttachActorToLeftHand(AActor* ActorToAttach) { if (Character == nullptr || Character->GetMesh() == nullptr || ActorToAttach == nullptr || PrimaryWeapon == nullptr) return; bool bUsePistolSocket = PrimaryWeapon->IsPistol() || PrimaryWeapon->IsSMG(); FName SocketName = bUsePistolSocket ? FName("LeftHandPistolSocket") : FName("LeftHandSocket"); const USkeletalMeshSocket* HandSocket = Character->GetMesh()->GetSocketByName(SocketName); if (HandSocket) { HandSocket->AttachActor(ActorToAttach, Character->GetMesh()); } } void UCombatComponent::AttachActorToBackpack(AActor* ActorToAttach) { if (Character == nullptr || Character->GetMesh() == nullptr|| ActorToAttach == nullptr) return; const USkeletalMeshSocket* BackpackSocket = Character->GetMesh()->GetSocketByName(FName("BackpackSocket")); if (BackpackSocket) { BackpackSocket->AttachActor(ActorToAttach, Character->GetMesh()); } } void UCombatComponent::UpdateCarriedAmmo() { if (PrimaryWeapon == nullptr) return; if (CarriedAmmoMap.Contains(PrimaryWeapon->GetWeaponType())) { CarriedAmmo = CarriedAmmoMap[PrimaryWeapon->GetWeaponType()]; } Controller = Controller == nullptr ? Cast(Character->Controller) : Controller; if (Controller) { Controller->SetHUDCarriedAmmo(CarriedAmmo); } } void UCombatComponent::PlayEquipWeaponSound(const AWeapon* Weapon) { if (Character && Weapon && Weapon->EquipSound) { UGameplayStatics::PlaySoundAtLocation( this, Weapon->EquipSound, Character->GetActorLocation() ); } } void UCombatComponent::ReloadEmptyWeapon() { if (PrimaryWeapon && PrimaryWeapon->IsEmpty()) { Reload(); } } void UCombatComponent::Reload() { if (CarriedAmmo > 0 && CombatState == ECombatState::ECS_Unoccupied) { ServerReload(); } } void UCombatComponent::DropWeapons() { if (PrimaryWeapon) PrimaryWeapon->Dropped(); if (SecondaryWeapon) SecondaryWeapon->Dropped(); } void UCombatComponent::ServerReload_Implementation() { if (Character == nullptr || PrimaryWeapon == nullptr) return; // return if weapon mag is at max capacity if (PrimaryWeapon->GetAmmo() == PrimaryWeapon->GetMagCapacity()) return; CombatState = ECombatState::ECS_Reloading; HandleReload(); } void UCombatComponent::FinishedReloading() { if (Character == nullptr) return; if (Character->HasAuthority()) { CombatState = ECombatState::ECS_Unoccupied; UpdateAmmoValues(); } if (bFireButtonPressed) { Fire(); } } void UCombatComponent::UpdateAmmoValues() { if (Character == nullptr || PrimaryWeapon == nullptr) return; int32 ReloadAmount = AmountToReload(); if (CarriedAmmoMap.Contains(PrimaryWeapon->GetWeaponType())) { CarriedAmmoMap[PrimaryWeapon->GetWeaponType()] -= ReloadAmount; CarriedAmmo = CarriedAmmoMap[PrimaryWeapon->GetWeaponType()]; } Controller = Controller == nullptr ? Cast(Character->Controller) : Controller; if (Controller) { Controller->SetHUDCarriedAmmo(CarriedAmmo); } PrimaryWeapon->AddAmmo(ReloadAmount); } void UCombatComponent::UpdateShotgunAmmoValues() { if (Character == nullptr || PrimaryWeapon == nullptr) return; if (CarriedAmmoMap.Contains(PrimaryWeapon->GetWeaponType())) { CarriedAmmoMap[PrimaryWeapon->GetWeaponType()] -= 1; CarriedAmmo = CarriedAmmoMap[PrimaryWeapon->GetWeaponType()]; } Controller = Controller == nullptr ? Cast(Character->Controller) : Controller; if (Controller) { Controller->SetHUDCarriedAmmo(CarriedAmmo); } PrimaryWeapon->AddAmmo(1); bCanFire = true; if (PrimaryWeapon->IsFull() || CarriedAmmo == 0) { JumpToShotgunEnd(); } } void UCombatComponent::JumpToShotgunEnd() { // Jump to ShotgunEnd section UAnimInstance* AnimInstance = Character->GetMesh()->GetAnimInstance(); if (AnimInstance && Character->GetReloadMontage()) { AnimInstance->Montage_JumpToSection(FName("ShotgunEnd")); } } void UCombatComponent::ThrowGrenadeFinished() { CombatState = ECombatState::ECS_Unoccupied; AttachActorToRightHand(PrimaryWeapon); } void UCombatComponent::LaunchGrenade() { ShowAttachedGrenade(false); if (Character && Character->IsLocallyControlled()) { ServerLaunchGrenade(HitTarget); } } void UCombatComponent::ServerLaunchGrenade_Implementation(const FVector_NetQuantize& Target) { if (Character && GrenadeClass && Character->GetAttachedGrenade()) { const FVector StartingLocation = Character->GetAttachedGrenade()->GetComponentLocation(); FVector ToTarget = Target - StartingLocation; FActorSpawnParameters SpawnParams; SpawnParams.Owner = Character; SpawnParams.Instigator = Character; UWorld* World = GetWorld(); if (World) { World->SpawnActor( GrenadeClass, StartingLocation + 10.f, ToTarget.Rotation(), SpawnParams ); } } } void UCombatComponent::OnRep_CombatState() { switch (CombatState) { case ECombatState::ECS_Reloading: HandleReload(); break; case ECombatState::ECS_Unoccupied: if (bFireButtonPressed) { Fire(); } break; case ECombatState::ECS_ThrowingGrenade: if (Character && !Character->IsLocallyControlled()) { Character->PlayThrowGrenadeMontage(); AttachActorToLeftHand(PrimaryWeapon); ShowAttachedGrenade(true); } break; } } void UCombatComponent::HandleReload() { Character->PlayReloadMontage(); } int32 UCombatComponent::AmountToReload() { if (PrimaryWeapon == nullptr) return 0; int32 RoomInMag = PrimaryWeapon->GetMagCapacity() - PrimaryWeapon->GetAmmo(); if (CarriedAmmoMap.Contains(PrimaryWeapon->GetWeaponType())) { int32 AmountCarried = CarriedAmmoMap[PrimaryWeapon->GetWeaponType()]; int32 Least = FMath::Min(RoomInMag, AmountCarried); return FMath::Clamp(RoomInMag, 0, Least); } return 0; } void UCombatComponent::ThrowGrenade() { if (Grenades == 0) return; if (CombatState != ECombatState::ECS_Unoccupied || PrimaryWeapon == nullptr) return; CombatState = ECombatState::ECS_ThrowingGrenade; if (Character) { Character->PlayThrowGrenadeMontage(); AttachActorToLeftHand(PrimaryWeapon); ShowAttachedGrenade(true); } if (Character && !Character->HasAuthority()) { ServerThrowGrenade(); } if (Character && Character->HasAuthority()) { Grenades = FMath::Clamp(Grenades -1, 0, MaxGrenades); UpdateHUDGrenades(); } } void UCombatComponent::ServerThrowGrenade_Implementation() { if (Grenades == 0) return; CombatState = ECombatState::ECS_ThrowingGrenade; if (Character) { Character->PlayThrowGrenadeMontage(); AttachActorToLeftHand(PrimaryWeapon); ShowAttachedGrenade(true); } Grenades = FMath::Clamp(Grenades -1, 0, MaxGrenades); UpdateHUDGrenades(); } void UCombatComponent::OnRep_Grenades() { UpdateHUDGrenades(); } void UCombatComponent::UpdateHUDGrenades() { Controller = Controller == nullptr ? Cast(Character->Controller) : Controller;Controller = Controller == nullptr ? Cast(Character->Controller) : Controller; if (Controller) { Controller->SetHUDGrenades(Grenades); } } void UCombatComponent::ShowAttachedGrenade(bool bShowGrenade) { if (Character && Character->GetAttachedGrenade()) { Character->GetAttachedGrenade()->SetVisibility(bShowGrenade); } } void UCombatComponent::TraceUnderCrosshairs(FHitResult& TraceHitResult) { FVector2D ViewportSize; if (GEngine && GEngine->GameViewport) { GEngine->GameViewport->GetViewportSize(ViewportSize); } FVector2D CrosshairLocation(ViewportSize.X / 2.f, ViewportSize.Y / 2.f); FVector CrosshairWorldPosition; FVector CrosshairWorldDirection; bool bScreenToWorld = UGameplayStatics::DeprojectScreenToWorld( UGameplayStatics::GetPlayerController(this, 0), CrosshairLocation, CrosshairWorldPosition, CrosshairWorldDirection ); if (bScreenToWorld) { FVector Start = CrosshairWorldPosition; if (Character) { float DistanceToCharacter = (Character->GetActorLocation() - Start).Size(); Start += CrosshairWorldDirection * (DistanceToCharacter + 100.f); } FVector End = Start + CrosshairWorldDirection * TRACE_LENGTH; GetWorld()->LineTraceSingleByChannel( TraceHitResult, Start, End, ECollisionChannel::ECC_Visibility ); if (TraceHitResult.GetActor() && TraceHitResult.GetActor()->Implements()) { HUDPackage.CrosshairsColor = FLinearColor::Red; } else { HUDPackage.CrosshairsColor = FLinearColor::White; } if (!TraceHitResult.bBlockingHit) TraceHitResult.ImpactPoint = End; } } void UCombatComponent::SetHUDCrosshairs(float DeltaTime) { if (Character == nullptr || Character->Controller == nullptr) return; Controller = Controller == nullptr ? Cast(Character->Controller) : Controller; if (Controller) { HUD = HUD == nullptr ? Cast(Controller->GetHUD()) : HUD; if (HUD) { if (PrimaryWeapon) { HUDPackage.CrosshairsCenter = PrimaryWeapon->CrosshairsCenter; HUDPackage.CrosshairsLeft = PrimaryWeapon->CrosshairsLeft; HUDPackage.CrosshairsRight = PrimaryWeapon->CrosshairsRight; HUDPackage.CrosshairsBottom = PrimaryWeapon->CrosshairsBottom; HUDPackage.CrosshairsTop = PrimaryWeapon->CrosshairsTop; } else { HUDPackage.CrosshairsCenter = nullptr; HUDPackage.CrosshairsLeft = nullptr; HUDPackage.CrosshairsRight = nullptr; HUDPackage.CrosshairsBottom = nullptr; HUDPackage.CrosshairsTop = nullptr; } // Calculate crosshair spread // [0, 600] -> [0, 1] FVector2D WalkSpeedRange(0.f, Character->GetCharacterMovement()->MaxWalkSpeed); FVector2D VelocityMultiplierRange(0.f, 1.f); FVector Velocity = Character->GetVelocity(); Velocity.Z = 0.f; CrosshairVelocityFactor = FMath::GetMappedRangeValueClamped(WalkSpeedRange, VelocityMultiplierRange, Velocity.Size()); if (Character->GetCharacterMovement()->IsFalling()) { CrosshairInAirFactor = FMath::FInterpTo(CrosshairInAirFactor, 2.25f, DeltaTime, 2.25f); } else { CrosshairInAirFactor = FMath::FInterpTo(CrosshairInAirFactor, 0.f, DeltaTime, 30.f); } if (bAiming) { CrosshairAimFactor = FMath::FInterpTo(CrosshairAimFactor, 0.58f, DeltaTime, 30.f); } else { CrosshairAimFactor = FMath::FInterpTo(CrosshairAimFactor, 0.f, DeltaTime, 30.f); } CrosshairShootingFactor = FMath::FInterpTo(CrosshairShootingFactor, 0.f, DeltaTime, 40.f); HUDPackage.CrosshairSpread = 0.5f + CrosshairVelocityFactor + CrosshairInAirFactor - CrosshairAimFactor + CrosshairShootingFactor; HUD->SetHUDPackage(HUDPackage); } } } void UCombatComponent::InterpFOV(float DeltaTime) { if (PrimaryWeapon == nullptr) return; if (bAiming) { CurrentFOV = FMath::FInterpTo(CurrentFOV, PrimaryWeapon->GetZoomedFOV(), DeltaTime, PrimaryWeapon->GetZoomInterpSpeed()); } else { CurrentFOV = FMath::FInterpTo(CurrentFOV, DefaultFOV, DeltaTime, ZoomInterpSpeed); } if (Character && Character->GetFollowCamera()) { Character->GetFollowCamera()->SetFieldOfView(CurrentFOV); } } void UCombatComponent::SetAiming(bool bIsAiming) { if (Character == nullptr || PrimaryWeapon == nullptr) return; bAiming = bIsAiming; ServerSetAiming(bIsAiming); if (Character) { Character->GetCharacterMovement()->MaxWalkSpeed = bIsAiming ? AimWalkSpeed : BaseWalkSpeed; } if (Character->IsLocallyControlled() && PrimaryWeapon->IsSniper()) { Character->ShowSniperScopeWidget(bIsAiming); } if (Character->IsLocallyControlled()) bAimButtonPressed = bIsAiming; } void UCombatComponent::ServerSetAiming_Implementation(bool bIsAiming) { bAiming = bIsAiming; if (Character) { Character->GetCharacterMovement()->MaxWalkSpeed = bIsAiming ? AimWalkSpeed : BaseWalkSpeed; } } void UCombatComponent::OnRep_Aiming() { if (Character && Character->IsLocallyControlled()) { bAiming = bAimButtonPressed; } } bool UCombatComponent::CanFire() { if (PrimaryWeapon == nullptr) return false; if (PrimaryWeapon->IsEmpty()) return false; if (!bCanFire) return false; if (CombatState == ECombatState::ECS_Reloading && PrimaryWeapon->GetWeaponType() == EWeaponType::EWT_Shotgun) return true; return CombatState == ECombatState::ECS_Unoccupied; } void UCombatComponent::OnRep_CarriedAmmo() { Controller = Controller == nullptr ? Cast(Character->Controller) : Controller; if (Controller) { Controller->SetHUDCarriedAmmo(CarriedAmmo); } bool bJumpToShotgunEnd = CombatState == ECombatState::ECS_Reloading && PrimaryWeapon != nullptr && PrimaryWeapon->GetWeaponType() == EWeaponType::EWT_Shotgun && CarriedAmmo == 0; if (bJumpToShotgunEnd) { JumpToShotgunEnd(); } } void UCombatComponent::InitializeCarriedAmmo() { CarriedAmmoMap.Emplace(EWeaponType::EWT_AssaultRifle, StartingARAmmo); CarriedAmmoMap.Emplace(EWeaponType::EWT_RocketLauncher, StartingRocketAmmo); CarriedAmmoMap.Emplace(EWeaponType::EWT_Pistol, StartingPistolAmmo); CarriedAmmoMap.Emplace(EWeaponType::EWT_SubmachineGun, StartingSMGAmmo); CarriedAmmoMap.Emplace(EWeaponType::EWT_Shotgun, StartingShotgunAmmo); CarriedAmmoMap.Emplace(EWeaponType::EWT_SniperRifle, StartingSniperAmmo); CarriedAmmoMap.Emplace(EWeaponType::EWT_GrenadeLauncher, StartingGrenadeLauncherAmmo); }