diff --git a/Content/Blueprints/GameModes/BP_BlasterGameMode.uasset b/Content/Blueprints/GameModes/BP_BlasterGameMode.uasset index 15b9ff2..fa9c0d0 100644 Binary files a/Content/Blueprints/GameModes/BP_BlasterGameMode.uasset and b/Content/Blueprints/GameModes/BP_BlasterGameMode.uasset differ diff --git a/Content/Blueprints/HUD/WBP_Announcement.uasset b/Content/Blueprints/HUD/WBP_Announcement.uasset index 6215a1c..5f5d058 100644 Binary files a/Content/Blueprints/HUD/WBP_Announcement.uasset and b/Content/Blueprints/HUD/WBP_Announcement.uasset differ diff --git a/Content/Maps/BlasterMap.umap b/Content/Maps/BlasterMap.umap index fe90ccd..8b77609 100644 Binary files a/Content/Maps/BlasterMap.umap and b/Content/Maps/BlasterMap.umap differ diff --git a/Source/Blaster/Character/BlasterCharacter.cpp b/Source/Blaster/Character/BlasterCharacter.cpp index 4d07751..88f645e 100644 --- a/Source/Blaster/Character/BlasterCharacter.cpp +++ b/Source/Blaster/Character/BlasterCharacter.cpp @@ -27,7 +27,7 @@ ABlasterCharacter::ABlasterCharacter() SpawnCollisionHandlingMethod = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn; CameraBoom = CreateDefaultSubobject(TEXT("CameraBoom")); CameraBoom->SetupAttachment(GetMesh()); - CameraBoom->TargetArmLength = 350.f; + CameraBoom->TargetArmLength = 600.f; CameraBoom->bUsePawnControlRotation = true; FollowCamera = CreateDefaultSubobject(TEXT("FollowCamera")); @@ -44,11 +44,12 @@ ABlasterCharacter::ABlasterCharacter() Combat->SetIsReplicated(true); GetCharacterMovement()->NavAgentProps.bCanCrouch = true; - GetCapsuleComponent()->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore); + GetCapsuleComponent()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Camera, ECollisionResponse::ECR_Ignore); GetMesh()->SetCollisionObjectType(ECC_SkeletalMesh); - GetMesh()->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore); - GetMesh()->SetCollisionResponseToChannel(ECC_Visibility, ECR_Block); - GetCharacterMovement()->RotationRate = FRotator(0.f, 850.f, 0.f); + GetMesh()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Camera, ECollisionResponse::ECR_Ignore); + GetMesh()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Visibility, ECollisionResponse::ECR_Block); + GetCharacterMovement()->RotationRate = FRotator(0.f, 0.f, 850.f); + TurningInPlace = ETurningInPlace::ETIP_NotTurning; NetUpdateFrequency = 66.f; MinNetUpdateFrequency = 33.f; @@ -56,17 +57,6 @@ ABlasterCharacter::ABlasterCharacter() DissolveTimeline = CreateDefaultSubobject(TEXT("DissolveTimelineComponent")); } -void ABlasterCharacter::BeginPlay() -{ - Super::BeginPlay(); - - UpdateHUDHealth(); - if (HasAuthority()) - { - OnTakeAnyDamage.AddDynamic(this, &ABlasterCharacter::ReceiveDamage); - } -} - void ABlasterCharacter::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); @@ -79,76 +69,10 @@ void ABlasterCharacter::GetLifetimeReplicatedProps(TArray& Ou void ABlasterCharacter::OnRep_ReplicatedMovement() { Super::OnRep_ReplicatedMovement(); - SimProxiesTurn(); TimeSinceLastMovementReplication = 0.f; } -void ABlasterCharacter::Destroyed() -{ - Super::Destroyed(); - - if (EliminationBotComponent) - { - EliminationBotComponent->DestroyComponent(); - } - if (Combat && Combat->EquippedWeapon) - { - Combat->EquippedWeapon->Destroy(); - } -} - -void ABlasterCharacter::PostInitializeComponents() -{ - Super::PostInitializeComponents(); - - if (Combat) - { - Combat->Character = this; - } -} - -void ABlasterCharacter::PlayFireMontage(bool bAiming) -{ - if (Combat == nullptr || Combat->EquippedWeapon == nullptr) return; - - UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance(); - if (AnimInstance && FireWeaponMontage) - { - AnimInstance->Montage_Play(FireWeaponMontage); - const FName SectionName = bAiming ? FName("RifleADS") : FName("RifleHip"); - AnimInstance->Montage_JumpToSection(SectionName); - } -} - -void ABlasterCharacter::PlayReloadMontage() -{ - if (Combat == nullptr || Combat->EquippedWeapon == nullptr) return; - - UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance(); - if (AnimInstance && ReloadMontage) - { - AnimInstance->Montage_Play(ReloadMontage); - FName SectionName; - switch (Combat->EquippedWeapon->GetWeaponType()) - { - case EWeaponType::EWT_AssaultRifle: - SectionName = FName("Rifle"); - break; - } - AnimInstance->Montage_JumpToSection(SectionName); - } -} - -void ABlasterCharacter::PlayEliminatedMontage() -{ - UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance(); - if (AnimInstance && EliminatedMontage) - { - AnimInstance->Montage_Play(EliminatedMontage); - } -} - void ABlasterCharacter::Eliminated() { if (Combat && Combat->EquippedWeapon) @@ -156,7 +80,12 @@ void ABlasterCharacter::Eliminated() Combat->EquippedWeapon->Dropped(); } MulticastEliminated(); - GetWorldTimerManager().SetTimer(EliminationTimer, this, &ABlasterCharacter::EliminationTimerFinished, EliminationDelay); + GetWorldTimerManager().SetTimer( + EliminationTimer, + this, + &ABlasterCharacter::EliminationTimerFinished, + EliminationDelay + ); } void ABlasterCharacter::MulticastEliminated_Implementation() @@ -182,7 +111,6 @@ void ABlasterCharacter::MulticastEliminated_Implementation() GetCharacterMovement()->DisableMovement(); GetCharacterMovement()->StopMovementImmediately(); bDisableGameplay = true; - // Disable collision GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision); GetMesh()->SetCollisionEnabled(ECollisionEnabled::NoCollision); @@ -190,13 +118,21 @@ void ABlasterCharacter::MulticastEliminated_Implementation() // Elimination bot if (EliminationBotEffect) { - const FVector EliminationBotSpawnPoint(GetActorLocation().X, GetActorLocation().Y, GetActorLocation().Z + 200.f); - EliminationBotComponent = UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), EliminationBotEffect, EliminationBotSpawnPoint, GetActorRotation()); - + FVector EliminationBotSpawnPoint(GetActorLocation().X, GetActorLocation().Y, GetActorLocation().Z + 200.f); + EliminationBotComponent = UGameplayStatics::SpawnEmitterAtLocation( + GetWorld(), + EliminationBotEffect, + EliminationBotSpawnPoint, + GetActorRotation() + ); } if (EliminationBotSound) { - UGameplayStatics::SpawnSoundAtLocation(this, EliminationBotSound, GetActorLocation()); + UGameplayStatics::SpawnSoundAtLocation( + this, + EliminationBotSound, + GetActorLocation() + ); } } @@ -209,40 +145,38 @@ void ABlasterCharacter::EliminationTimerFinished() } } -void ABlasterCharacter::PlayHitReactMontage() +void ABlasterCharacter::Destroyed() { - if (Combat == nullptr || Combat->EquippedWeapon == nullptr) return; + Super::Destroyed(); - UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance(); - if (AnimInstance && HitReactMontage) + if (EliminationBotComponent) { - AnimInstance->Montage_Play(HitReactMontage); - const FName SectionName = FName("FromFront"); - AnimInstance->Montage_JumpToSection(SectionName); + EliminationBotComponent->DestroyComponent(); + } + if (Combat && Combat->EquippedWeapon) + { + Combat->EquippedWeapon->Destroy(); } } -void ABlasterCharacter::ReceiveDamage(AActor* DamagedActor, float Damage, const UDamageType* DamageType, AController* InstigatorController, - AActor* DamageCauser) +void ABlasterCharacter::BeginPlay() { - Health = FMath::Clamp(Health - Damage, 0.f, MaxHealth); + Super::BeginPlay(); UpdateHUDHealth(); - if (Health > 0.f) + if (HasAuthority()) { - PlayHitReactMontage(); + OnTakeAnyDamage.AddDynamic(this, &ABlasterCharacter::ReceiveDamage); } +} - if (Health == 0.f) - { - ABlasterGameMode* GameMode = GetWorld()->GetAuthGameMode(); - if (GameMode) - { - BlasterPlayerController = BlasterPlayerController == nullptr ? Cast(Controller) : BlasterPlayerController; - ABlasterPlayerController* AttackerController = Cast(InstigatorController); - GameMode->PlayerEliminated(this, BlasterPlayerController, AttackerController); - } - } +void ABlasterCharacter::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + + RotateInPlace(DeltaTime); + HideCameraIfCharacterClose(); + PollInit(); } void ABlasterCharacter::RotateInPlace(float DeltaTime) @@ -253,7 +187,7 @@ void ABlasterCharacter::RotateInPlace(float DeltaTime) TurningInPlace = ETurningInPlace::ETIP_NotTurning; return; } - if (GetLocalRole() > ROLE_SimulatedProxy && IsLocallyControlled()) + if (GetLocalRole() > ENetRole::ROLE_SimulatedProxy && IsLocallyControlled()) { AimOffset(DeltaTime); } @@ -268,46 +202,108 @@ void ABlasterCharacter::RotateInPlace(float DeltaTime) } } -void ABlasterCharacter::Tick(float DeltaTime) -{ - Super::Tick(DeltaTime); - - RotateInPlace(DeltaTime); - HideCameraIfCharacterClose(); - PollInit(); -} - -void ABlasterCharacter::PollInit() -{ - if (BlasterPlayerState == nullptr) - { - BlasterPlayerState = GetPlayerState(); - if (BlasterPlayerState) - { - // Initialize Score now we have the PlayerState - BlasterPlayerState->IncreaseScore(0.f); - BlasterPlayerState->IncreaseDefeats(0); - } - } -} - void ABlasterCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ABlasterCharacter::Jump); - PlayerInputComponent->BindAction("Equip", IE_Pressed, this, &ABlasterCharacter::EquipButtonPressed); - PlayerInputComponent->BindAction("Reload", IE_Pressed, this, &ABlasterCharacter::ReloadButtonPressed); - PlayerInputComponent->BindAction("Crouch", IE_Pressed, this, &ABlasterCharacter::CrouchButtonPressed); - PlayerInputComponent->BindAction("Aim", IE_Pressed, this, &ABlasterCharacter::AimButtonPressed); - PlayerInputComponent->BindAction("Aim", IE_Released, this, &ABlasterCharacter::AimButtonReleased); - PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &ABlasterCharacter::FireButtonPressed); - PlayerInputComponent->BindAction("Fire", IE_Released, this, &ABlasterCharacter::FireButtonReleased); PlayerInputComponent->BindAxis("MoveForward", this, &ABlasterCharacter::MoveForward); PlayerInputComponent->BindAxis("MoveRight", this, &ABlasterCharacter::MoveRight); PlayerInputComponent->BindAxis("Turn", this, &ABlasterCharacter::Turn); PlayerInputComponent->BindAxis("LookUp", this, &ABlasterCharacter::LookUp); + + PlayerInputComponent->BindAction("Equip", IE_Pressed, this, &ABlasterCharacter::EquipButtonPressed); + PlayerInputComponent->BindAction("Crouch", IE_Pressed, this, &ABlasterCharacter::CrouchButtonPressed); + PlayerInputComponent->BindAction("Aim", IE_Pressed, this, &ABlasterCharacter::AimButtonPressed); + PlayerInputComponent->BindAction("Aim", IE_Released, this, &ABlasterCharacter::AimButtonReleased); + PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &ABlasterCharacter::FireButtonPressed); + PlayerInputComponent->BindAction("Fire", IE_Released, this, &ABlasterCharacter::FireButtonReleased); + PlayerInputComponent->BindAction("Reload", IE_Pressed, this, &ABlasterCharacter::ReloadButtonPressed); +} + +void ABlasterCharacter::PostInitializeComponents() +{ + Super::PostInitializeComponents(); + if (Combat) + { + Combat->Character = this; + } +} + +void ABlasterCharacter::PlayFireMontage(bool bAiming) +{ + if (Combat == nullptr || Combat->EquippedWeapon == nullptr) return; + + UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance(); + if (AnimInstance && FireWeaponMontage) + { + AnimInstance->Montage_Play(FireWeaponMontage); + FName SectionName; + SectionName = bAiming ? FName("RifleAim") : FName("RifleHip"); + AnimInstance->Montage_JumpToSection(SectionName); + } +} + +void ABlasterCharacter::PlayReloadMontage() +{ + if (Combat == nullptr || Combat->EquippedWeapon == nullptr) return; + + UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance(); + if (AnimInstance && ReloadMontage) + { + AnimInstance->Montage_Play(ReloadMontage); + FName SectionName; + + switch (Combat->EquippedWeapon->GetWeaponType()) + { + case EWeaponType::EWT_AssaultRifle: + SectionName = FName("Rifle"); + break; + } + + AnimInstance->Montage_JumpToSection(SectionName); + } +} + +void ABlasterCharacter::PlayEliminatedMontage() +{ + UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance(); + if (AnimInstance && EliminatedMontage) + { + AnimInstance->Montage_Play(EliminatedMontage); + } +} + +void ABlasterCharacter::PlayHitReactMontage() +{ + if (Combat == nullptr || Combat->EquippedWeapon == nullptr) return; + + UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance(); + if (AnimInstance && HitReactMontage) + { + AnimInstance->Montage_Play(HitReactMontage); + FName SectionName("FromFront"); + AnimInstance->Montage_JumpToSection(SectionName); + } +} + +void ABlasterCharacter::ReceiveDamage(AActor* DamagedActor, float Damage, const UDamageType* DamageType, AController* InstigatorController, AActor* DamageCauser) +{ + Health = FMath::Clamp(Health - Damage, 0.f, MaxHealth); + UpdateHUDHealth(); + if (Health > 0.f) PlayHitReactMontage(); + + if (Health == 0.f) + { + ABlasterGameMode* BlasterGameMode = GetWorld()->GetAuthGameMode(); + if (BlasterGameMode) + { + BlasterPlayerController = BlasterPlayerController == nullptr ? Cast(Controller) : BlasterPlayerController; + ABlasterPlayerController* AttackerController = Cast(InstigatorController); + BlasterGameMode->PlayerEliminated(this, BlasterPlayerController, AttackerController); + } + } } void ABlasterCharacter::MoveForward(float Value) @@ -317,7 +313,6 @@ void ABlasterCharacter::MoveForward(float Value) { const FRotator YawRotation(0.f, Controller->GetControlRotation().Yaw, 0.f); const FVector Direction(FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X)); - AddMovementInput(Direction, Value); } } @@ -329,7 +324,6 @@ void ABlasterCharacter::MoveRight(float Value) { const FRotator YawRotation(0.f, Controller->GetControlRotation().Yaw, 0.f); const FVector Direction(FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y)); - AddMovementInput(Direction, Value); } } @@ -360,12 +354,11 @@ void ABlasterCharacter::EquipButtonPressed() } } -void ABlasterCharacter::ReloadButtonPressed() +void ABlasterCharacter::ServerEquipButtonPressed_Implementation() { - if (bDisableGameplay) return; if (Combat) { - Combat->Reload(); + Combat->EquipWeapon(OverlappingWeapon); } } @@ -382,6 +375,15 @@ void ABlasterCharacter::CrouchButtonPressed() } } +void ABlasterCharacter::ReloadButtonPressed() +{ + if (bDisableGameplay) return; + if (Combat) + { + Combat->Reload(); + } +} + void ABlasterCharacter::AimButtonPressed() { if (bDisableGameplay) return; @@ -400,47 +402,24 @@ void ABlasterCharacter::AimButtonReleased() } } -void ABlasterCharacter::Jump() +float ABlasterCharacter::CalculateSpeed() { - if (bDisableGameplay) return; - if (bIsCrouched) - { - UnCrouch(); - } - else - { - Super::Jump(); - } -} - -void ABlasterCharacter::FireButtonPressed() -{ - if (Combat) - { - Combat->FireButtonPressed(true); - } -} - -void ABlasterCharacter::FireButtonReleased() -{ - if (Combat) - { - Combat->FireButtonPressed(false); - } + FVector Velocity = GetVelocity(); + Velocity.Z = 0.f; + return Velocity.Size(); } void ABlasterCharacter::AimOffset(float DeltaTime) { if (Combat && Combat->EquippedWeapon == nullptr) return; - - const float Speed = CalculateSpeed(); - const bool bIsInAir = GetCharacterMovement()->IsFalling(); + float Speed = CalculateSpeed(); + bool bIsInAir = GetCharacterMovement()->IsFalling(); - if (Speed == 0.f && !bIsInAir) // Standing still, not jumping + if (Speed == 0.f && !bIsInAir) // standing still, not jumping { bRotateRootBone = true; - const FRotator CurrentAimRotation = FRotator(0.f, GetBaseAimRotation().Yaw, 0.f); - const FRotator DeltaAimRotation = UKismetMathLibrary::NormalizedDeltaRotator(CurrentAimRotation, StartingAimRotation); + FRotator CurrentAimRotation = FRotator(0.f, GetBaseAimRotation().Yaw, 0.f); + FRotator DeltaAimRotation = UKismetMathLibrary::NormalizedDeltaRotator(CurrentAimRotation, StartingAimRotation); AO_Yaw = DeltaAimRotation.Yaw; if (TurningInPlace == ETurningInPlace::ETIP_NotTurning) { @@ -449,7 +428,7 @@ void ABlasterCharacter::AimOffset(float DeltaTime) bUseControllerRotationYaw = true; TurnInPlace(DeltaTime); } - if (Speed > 0.f || bIsInAir) // Running or jumping + if (Speed > 0.f || bIsInAir) // running, or jumping { bRotateRootBone = false; StartingAimRotation = FRotator(0.f, GetBaseAimRotation().Yaw, 0.f); @@ -464,13 +443,11 @@ void ABlasterCharacter::AimOffset(float DeltaTime) void ABlasterCharacter::CalculateAO_Pitch() { AO_Pitch = GetBaseAimRotation().Pitch; - - // Fix pitch/yaw compression if (AO_Pitch > 90.f && !IsLocallyControlled()) { // map pitch from [270, 360) to [-90, 0) - const FVector2d InRange(270.f, 360.f); - const FVector2d OutRange(-90.f, 0.f); + FVector2D InRange(270.f, 360.f); + FVector2D OutRange(-90.f, 0.f); AO_Pitch = FMath::GetMappedRangeValueClamped(InRange, OutRange, AO_Pitch); } } @@ -478,20 +455,18 @@ void ABlasterCharacter::CalculateAO_Pitch() void ABlasterCharacter::SimProxiesTurn() { if (Combat == nullptr || Combat->EquippedWeapon == nullptr) return; - bRotateRootBone = false; - - const float Speed = CalculateSpeed(); + float Speed = CalculateSpeed(); if (Speed > 0.f) { TurningInPlace = ETurningInPlace::ETIP_NotTurning; return; } - + ProxyRotationLastFrame = ProxyRotation; ProxyRotation = GetActorRotation(); ProxyYaw = UKismetMathLibrary::NormalizedDeltaRotator(ProxyRotation, ProxyRotationLastFrame).Yaw; - + if (FMath::Abs(ProxyYaw) > TurnThreshold) { if (ProxyYaw > TurnThreshold) @@ -508,13 +483,38 @@ void ABlasterCharacter::SimProxiesTurn() } return; } - TurningInPlace = ETurningInPlace::ETIP_NotTurning; } -void ABlasterCharacter::ServerEquipButtonPressed_Implementation() +void ABlasterCharacter::Jump() { - EquipButtonPressed(); + if (bDisableGameplay) return; + if (bIsCrouched) + { + UnCrouch(); + } + else + { + Super::Jump(); + } +} + +void ABlasterCharacter::FireButtonPressed() +{ + if (bDisableGameplay) return; + if (Combat) + { + Combat->FireButtonPressed(true); + } +} + +void ABlasterCharacter::FireButtonReleased() +{ + if (bDisableGameplay) return; + if (Combat) + { + Combat->FireButtonPressed(false); + } } void ABlasterCharacter::TurnInPlace(float DeltaTime) @@ -537,18 +537,6 @@ void ABlasterCharacter::TurnInPlace(float DeltaTime) StartingAimRotation = FRotator(0.f, GetBaseAimRotation().Yaw, 0.f); } } - // switch (TurningInPlace) - // { - // case ETurningInPlace::ETIP_Left: - // UE_LOG(LogTemp, Warning, TEXT("TurningInPlace: Left")); - // break; - // case ETurningInPlace::ETIP_Right: - // UE_LOG(LogTemp, Warning, TEXT("TurningInPlace: Right")); - // break; - // case ETurningInPlace::ETIP_NotTurning: - // UE_LOG(LogTemp, Warning, TEXT("TurningInPlace: NotTurning")); - // break; - // } } void ABlasterCharacter::HideCameraIfCharacterClose() @@ -572,20 +560,10 @@ void ABlasterCharacter::HideCameraIfCharacterClose() } } -float ABlasterCharacter::CalculateSpeed() -{ - FVector Velocity = GetVelocity(); - Velocity.Z = 0.f; - return Velocity.Size(); -} - void ABlasterCharacter::OnRep_Health() { UpdateHUDHealth(); - if (Health > 0.f) - { - PlayHitReactMontage(); - } + if (Health > 0.f) PlayHitReactMontage(); } void ABlasterCharacter::UpdateHUDHealth() @@ -597,6 +575,19 @@ void ABlasterCharacter::UpdateHUDHealth() } } +void ABlasterCharacter::PollInit() +{ + if (BlasterPlayerState == nullptr) + { + BlasterPlayerState = GetPlayerState(); + if (BlasterPlayerState) + { + BlasterPlayerState->AddToScore(0.f); + BlasterPlayerState->AddToDefeats(0); + } + } +} + void ABlasterCharacter::UpdateDissolveMaterial(float DissolveValue) { if (DynamicDissolveMaterialInstance) @@ -621,7 +612,6 @@ void ABlasterCharacter::SetOverlappingWeapon(AWeapon* Weapon) { OverlappingWeapon->ShowPickupWidget(false); } - OverlappingWeapon = Weapon; if (IsLocallyControlled()) { @@ -632,6 +622,18 @@ void ABlasterCharacter::SetOverlappingWeapon(AWeapon* Weapon) } } +void ABlasterCharacter::OnRep_OverlappingWeapon(AWeapon* LastWeapon) +{ + if (OverlappingWeapon) + { + OverlappingWeapon->ShowPickupWidget(true); + } + if (LastWeapon) + { + LastWeapon->ShowPickupWidget(false); + } +} + bool ABlasterCharacter::IsWeaponEquipped() { return Combat && Combat->EquippedWeapon; @@ -645,14 +647,12 @@ bool ABlasterCharacter::IsAiming() AWeapon* ABlasterCharacter::GetEquippedWeapon() { if (Combat == nullptr) return nullptr; - return Combat->EquippedWeapon; } FVector ABlasterCharacter::GetHitTarget() const { if (Combat == nullptr) return FVector(); - return Combat->HitTarget; } @@ -660,16 +660,4 @@ ECombatState ABlasterCharacter::GetCombatState() const { if (Combat == nullptr) return ECombatState::ECS_MAX; return Combat->CombatState; -} - -void ABlasterCharacter::OnRep_OverlappingWeapon(AWeapon* LastWeapon) -{ - if (OverlappingWeapon) - { - OverlappingWeapon->ShowPickupWidget(true); - } - if (LastWeapon) - { - LastWeapon->ShowPickupWidget(false); - } -} +} \ No newline at end of file diff --git a/Source/Blaster/Character/BlasterCharacter.h b/Source/Blaster/Character/BlasterCharacter.h index eeca674..08a129c 100644 --- a/Source/Blaster/Character/BlasterCharacter.h +++ b/Source/Blaster/Character/BlasterCharacter.h @@ -3,7 +3,7 @@ #pragma once #include "CoreMinimal.h" -#include "Blaster/Interfaces/InteractWithCrosshairInterface.h" +#include "Blaster/Interfaces/InteractWithCrosshairsInterface.h" #include "Blaster/Types/CombatState.h" #include "Blaster/Types/TurningInPlace.h" #include "Components/TimelineComponent.h" @@ -12,7 +12,7 @@ #include "BlasterCharacter.generated.h" UCLASS() -class BLASTER_API ABlasterCharacter : public ACharacter, public IInteractWithCrosshairInterface +class BLASTER_API ABlasterCharacter : public ACharacter, public IInteractWithCrosshairsInterface { GENERATED_BODY() diff --git a/Source/Blaster/Components/CombatComponent.cpp b/Source/Blaster/Components/CombatComponent.cpp index 6cfba8e..b4d6e34 100644 --- a/Source/Blaster/Components/CombatComponent.cpp +++ b/Source/Blaster/Components/CombatComponent.cpp @@ -4,6 +4,7 @@ #include "CombatComponent.h" #include "Blaster/Character/BlasterCharacter.h" +#include "Blaster/Interfaces/InteractWithCrosshairsInterface.h" #include "Blaster/PlayerController/BlasterPlayerController.h" #include "Blaster/Weapon/Weapon.h" #include "Camera/CameraComponent.h" @@ -17,7 +18,7 @@ UCombatComponent::UCombatComponent() PrimaryComponentTick.bCanEverTick = true; BaseWalkSpeed = 600.f; - AimWalkSpeed = 350.f; + AimWalkSpeed = 450.f; } void UCombatComponent::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const @@ -25,8 +26,8 @@ void UCombatComponent::GetLifetimeReplicatedProps(TArray& Out Super::GetLifetimeReplicatedProps(OutLifetimeProps); DOREPLIFETIME(UCombatComponent, EquippedWeapon); - DOREPLIFETIME_CONDITION(UCombatComponent, CarriedAmmo, COND_OwnerOnly); DOREPLIFETIME(UCombatComponent, bAiming); + DOREPLIFETIME_CONDITION(UCombatComponent, CarriedAmmo, COND_OwnerOnly); DOREPLIFETIME(UCombatComponent, CombatState); } @@ -65,6 +66,273 @@ void UCombatComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActo } } +void UCombatComponent::FireButtonPressed(bool bPressed) +{ + bFireButtonPressed = bPressed; + if (bFireButtonPressed && EquippedWeapon) + { + Fire(); + } +} + +void UCombatComponent::Fire() +{ + if (CanFire()) + { + bCanFire = false; + ServerFire(HitTarget); + if (EquippedWeapon) + { + CrosshairShootingFactor = .75f; + } + StartFireTimer(); + } +} + +void UCombatComponent::StartFireTimer() +{ + if (EquippedWeapon == nullptr || Character == nullptr) return; + Character->GetWorldTimerManager().SetTimer( + FireTimer, + this, + &UCombatComponent::FireTimerFinished, + EquippedWeapon->FireDelay + ); +} + +void UCombatComponent::FireTimerFinished() +{ + if (EquippedWeapon == nullptr) return; + bCanFire = true; + if (bFireButtonPressed && EquippedWeapon->bAutomatic) + { + Fire(); + } + if (EquippedWeapon->IsEmpty()) + { + Reload(); + } +} + +void UCombatComponent::ServerFire_Implementation(const FVector_NetQuantize& TraceHitTarget) +{ + MulticastFire(TraceHitTarget); +} + +void UCombatComponent::MulticastFire_Implementation(const FVector_NetQuantize& TraceHitTarget) +{ + if (EquippedWeapon == nullptr) return; + if (Character && CombatState == ECombatState::ECS_Unoccupied) + { + Character->PlayFireMontage(bAiming); + EquippedWeapon->Fire(TraceHitTarget); + } +} + +void UCombatComponent::EquipWeapon(AWeapon* WeaponToEquip) +{ + if (Character == nullptr || WeaponToEquip == nullptr) return; + if (EquippedWeapon) + { + EquippedWeapon->Dropped(); + } + EquippedWeapon = WeaponToEquip; + EquippedWeapon->SetWeaponState(EWeaponState::EWS_Equipped); + const USkeletalMeshSocket* HandSocket = Character->GetMesh()->GetSocketByName(FName("RightHandSocket")); + if (HandSocket) + { + HandSocket->AttachActor(EquippedWeapon, Character->GetMesh()); + } + EquippedWeapon->SetOwner(Character); + EquippedWeapon->SetHUDAmmo(); + + if (CarriedAmmoMap.Contains(EquippedWeapon->GetWeaponType())) + { + CarriedAmmo = CarriedAmmoMap[EquippedWeapon->GetWeaponType()]; + } + + Controller = Controller == nullptr ? Cast(Character->Controller) : Controller; + if (Controller) + { + Controller->SetHUDCarriedAmmo(CarriedAmmo); + } + + if (EquippedWeapon->EquipSound) + { + UGameplayStatics::PlaySoundAtLocation( + this, + EquippedWeapon->EquipSound, + Character->GetActorLocation() + ); + } + + if (EquippedWeapon->IsEmpty()) + { + Reload(); + } + + Character->GetCharacterMovement()->bOrientRotationToMovement = false; + Character->bUseControllerRotationYaw = true; +} + +void UCombatComponent::Reload() +{ + if (CarriedAmmo > 0 && CombatState != ECombatState::ECS_Reloading) + { + ServerReload(); + } +} + +void UCombatComponent::ServerReload_Implementation() +{ + if (Character == nullptr || EquippedWeapon == nullptr) return; + + // return if weapon mag is at max capacity + if (EquippedWeapon->GetAmmo() == EquippedWeapon->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 || EquippedWeapon == nullptr) return; + int32 ReloadAmount = AmountToReload(); + if (CarriedAmmoMap.Contains(EquippedWeapon->GetWeaponType())) + { + CarriedAmmoMap[EquippedWeapon->GetWeaponType()] -= ReloadAmount; + CarriedAmmo = CarriedAmmoMap[EquippedWeapon->GetWeaponType()]; + } + Controller = Controller == nullptr ? Cast(Character->Controller) : Controller; + if (Controller) + { + Controller->SetHUDCarriedAmmo(CarriedAmmo); + } + EquippedWeapon->AddAmmo(-ReloadAmount); +} + +void UCombatComponent::OnRep_CombatState() +{ + switch (CombatState) + { + case ECombatState::ECS_Reloading: + HandleReload(); + break; + case ECombatState::ECS_Unoccupied: + if (bFireButtonPressed) + { + Fire(); + } + break; + } +} + +void UCombatComponent::HandleReload() +{ + Character->PlayReloadMontage(); +} + +int32 UCombatComponent::AmountToReload() +{ + if (EquippedWeapon == nullptr) return 0; + int32 RoomInMag = EquippedWeapon->GetMagCapacity() - EquippedWeapon->GetAmmo(); + + if (CarriedAmmoMap.Contains(EquippedWeapon->GetWeaponType())) + { + int32 AmountCarried = CarriedAmmoMap[EquippedWeapon->GetWeaponType()]; + int32 Least = FMath::Min(RoomInMag, AmountCarried); + return FMath::Clamp(RoomInMag, 0, Least); + } + return 0; +} + +void UCombatComponent::OnRep_EquippedWeapon() +{ + if (EquippedWeapon && Character) + { + EquippedWeapon->SetWeaponState(EWeaponState::EWS_Equipped); + const USkeletalMeshSocket* HandSocket = Character->GetMesh()->GetSocketByName(FName("RightHandSocket")); + if (HandSocket) + { + HandSocket->AttachActor(EquippedWeapon, Character->GetMesh()); + } + Character->GetCharacterMovement()->bOrientRotationToMovement = false; + Character->bUseControllerRotationYaw = true; + + if (EquippedWeapon->EquipSound) + { + UGameplayStatics::PlaySoundAtLocation( + this, + EquippedWeapon->EquipSound, + Character->GetActorLocation() + ); + } + } +} + +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; @@ -80,22 +348,22 @@ void UCombatComponent::SetHUDCrosshairs(float DeltaTime) HUDPackage.CrosshairsCenter = EquippedWeapon->CrosshairsCenter; HUDPackage.CrosshairsLeft = EquippedWeapon->CrosshairsLeft; HUDPackage.CrosshairsRight = EquippedWeapon->CrosshairsRight; - HUDPackage.CrosshairsTop = EquippedWeapon->CrosshairsTop; HUDPackage.CrosshairsBottom = EquippedWeapon->CrosshairsBottom; + HUDPackage.CrosshairsTop = EquippedWeapon->CrosshairsTop; } else { HUDPackage.CrosshairsCenter = nullptr; HUDPackage.CrosshairsLeft = nullptr; HUDPackage.CrosshairsRight = nullptr; - HUDPackage.CrosshairsTop = nullptr; HUDPackage.CrosshairsBottom = nullptr; + HUDPackage.CrosshairsTop = nullptr; } - // Calculate crosshair spread - // Velocity [0, 600] -> Spread [0, 1] - const FVector2D WalkSpeedRange(0.f, Character->GetCharacterMovement()->MaxWalkSpeed); - const FVector2D VelocityMultiplierRange(0.f, 1.f); + + // [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; @@ -170,59 +438,9 @@ void UCombatComponent::ServerSetAiming_Implementation(bool bIsAiming) } } -void UCombatComponent::Fire() -{ - if (CanFire()) - { - bCanFire = false; - ServerFire(HitTarget); - - if (EquippedWeapon) - { - CrosshairShootingFactor = 0.75f; - } - - StartFireTimer(); - } - -} - -void UCombatComponent::FireButtonPressed(bool bPressed) -{ - bFireButtonPressed = bPressed; - - if (bFireButtonPressed && EquippedWeapon) - { - Fire(); - } -} - -void UCombatComponent::StartFireTimer() -{ - if (EquippedWeapon == nullptr || Character == nullptr) return; - - Character->GetWorldTimerManager().SetTimer(FireTimer, this, &UCombatComponent::FireTimerFinished, EquippedWeapon->FireDelay); -} - -void UCombatComponent::FireTimerFinished() -{ - if (EquippedWeapon == nullptr) return; - - bCanFire = true; - if (bFireButtonPressed && EquippedWeapon->bAutomatic) - { - Fire(); - } - if (EquippedWeapon->IsEmpty()) - { - Reload(); - } -} - bool UCombatComponent::CanFire() { if (EquippedWeapon == nullptr) return false; - return !EquippedWeapon->IsEmpty() && bCanFire && CombatState == ECombatState::ECS_Unoccupied; } @@ -239,212 +457,3 @@ void UCombatComponent::InitializeCarriedAmmo() { CarriedAmmoMap.Emplace(EWeaponType::EWT_AssaultRifle, StartingARAmmo); } - -void UCombatComponent::ServerFire_Implementation(const FVector_NetQuantize& TraceHitTarget) -{ - MulticastFire(TraceHitTarget); -} - -void UCombatComponent::MulticastFire_Implementation(const FVector_NetQuantize& TraceHitTarget) -{ - if (EquippedWeapon == nullptr) return; - if (Character && CombatState == ECombatState::ECS_Unoccupied) - { - Character->PlayFireMontage(bAiming); - EquippedWeapon->Fire(TraceHitTarget); - } -} - -void UCombatComponent::TraceUnderCrosshairs(FHitResult& TraceHitResult) -{ - FVector2d ViewPortSize; - if (GEngine && GEngine->GameViewport) - { - GEngine->GameViewport->GetViewportSize(ViewPortSize); - } - - FVector2d CrosshairLocation(ViewPortSize.X / 2.f, ViewPortSize.Y / 2.0f); - 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 + 60.f); - } - FVector End = Start + CrosshairWorldDirection * TRACE_LENGTH; - - GetWorld()->LineTraceSingleByChannel( - TraceHitResult, - Start, - End, - ECollisionChannel::ECC_Visibility - ); - if (TraceHitResult.GetActor() && TraceHitResult.GetActor()->Implements()) - { - HUDPackage.CrosshairColor = FLinearColor::Red; - } - else - { - HUDPackage.CrosshairColor = FLinearColor::White; - } - - if (!TraceHitResult.bBlockingHit) TraceHitResult.ImpactPoint = End; - } -} - -void UCombatComponent::EquipWeapon(AWeapon* WeaponToEquip) -{ - if (Character == nullptr || WeaponToEquip == nullptr) return; - if (EquippedWeapon) - { - EquippedWeapon->Dropped(); - } - EquippedWeapon = WeaponToEquip; - EquippedWeapon->SetWeaponState(EWeaponState::EWS_Equipped); - const USkeletalMeshSocket* HandSocket = Character->GetMesh()->GetSocketByName(FName("RightHandSocket")); - if (HandSocket) - { - HandSocket->AttachActor(EquippedWeapon, Character->GetMesh()); - } - EquippedWeapon->SetOwner(Character); - EquippedWeapon->SetHUDAmmo(); - - if (CarriedAmmoMap.Contains(EquippedWeapon->GetWeaponType())) - { - CarriedAmmo = CarriedAmmoMap[EquippedWeapon->GetWeaponType()]; - } - - Controller = Controller == nullptr ? Cast(Character->Controller) : Controller; - if (Controller) - { - Controller->SetHUDCarriedAmmo(CarriedAmmo); - } - - if (EquippedWeapon->EquipSound) - { - UGameplayStatics::PlaySoundAtLocation(this, EquippedWeapon->EquipSound, Character->GetActorLocation()); - } - - if (EquippedWeapon->IsEmpty()) - { - Reload(); - } - Character->GetCharacterMovement()->bOrientRotationToMovement = false; - Character->bUseControllerRotationYaw = true; -} - -void UCombatComponent::Reload() -{ - if (CarriedAmmo > 0 && CombatState != ECombatState::ECS_Reloading) - { - ServerReload(); - } -} - -void UCombatComponent::FinishedReloading() -{ - if (Character == nullptr) return; - if (Character->HasAuthority()) - { - CombatState = ECombatState::ECS_Unoccupied; - UpdateAmmoValues(); - } - if (bFireButtonPressed) - { - Fire(); - } -} - -void UCombatComponent::UpdateAmmoValues() -{ - if (Character == nullptr || EquippedWeapon == nullptr) return; - const int32 ReloadAmount = AmountToReload(); - if (CarriedAmmoMap.Contains(EquippedWeapon->GetWeaponType())) - { - CarriedAmmoMap[EquippedWeapon->GetWeaponType()] -= ReloadAmount; - CarriedAmmo = CarriedAmmoMap[EquippedWeapon->GetWeaponType()]; - } - Controller = Controller == nullptr ? Cast(Character->Controller) : Controller; - if (Controller) - { - Controller->SetHUDCarriedAmmo(CarriedAmmo); - } - EquippedWeapon->AddAmmo(-ReloadAmount); -} - -void UCombatComponent::ServerReload_Implementation() -{ - if (Character == nullptr || EquippedWeapon == nullptr) return; - - // return if weapon mag is at max capacity - if (EquippedWeapon->GetAmmo() == EquippedWeapon->GetMagCapacity()) return; - - CombatState = ECombatState::ECS_Reloading; - HandleReload(); -} - -void UCombatComponent::OnRep_CombatState() -{ - switch (CombatState) - { - case ECombatState::ECS_Reloading: - HandleReload(); - break; - case ECombatState::ECS_Unoccupied: - if (bFireButtonPressed) - { - Fire(); - } - break; - } -} - -void UCombatComponent::HandleReload() -{ - Character->PlayReloadMontage(); -} - -int32 UCombatComponent::AmountToReload() -{ - if (EquippedWeapon == nullptr) return 0; - - const int32 RoomInMag = EquippedWeapon->GetMagCapacity() - EquippedWeapon->GetAmmo(); - - if (CarriedAmmoMap.Contains(EquippedWeapon->GetWeaponType())) - { - const int32 AmountCarried = CarriedAmmoMap[EquippedWeapon->GetWeaponType()]; - const int32 Least = FMath::Min(RoomInMag, AmountCarried); - return FMath::Clamp(RoomInMag, 0, Least); - } - - return 0; -} - -void UCombatComponent::OnRep_EquippedWeapon() -{ - if (EquippedWeapon && Character) - { - EquippedWeapon->SetWeaponState(EWeaponState::EWS_Equipped); - const USkeletalMeshSocket* HandSocket = Character->GetMesh()->GetSocketByName(FName("RightHandSocket")); - if (HandSocket) - { - HandSocket->AttachActor(EquippedWeapon, Character->GetMesh()); - } - if (EquippedWeapon->EquipSound) - { - UGameplayStatics::PlaySoundAtLocation(this, EquippedWeapon->EquipSound, Character->GetActorLocation()); - } - Character->GetCharacterMovement()->bOrientRotationToMovement = false; - Character->bUseControllerRotationYaw = true; - } -} diff --git a/Source/Blaster/GameMode/BlasterGameMode.cpp b/Source/Blaster/GameMode/BlasterGameMode.cpp index a1075f4..05824fe 100644 --- a/Source/Blaster/GameMode/BlasterGameMode.cpp +++ b/Source/Blaster/GameMode/BlasterGameMode.cpp @@ -2,13 +2,11 @@ #include "BlasterGameMode.h" - #include "Blaster/Character/BlasterCharacter.h" #include "Blaster/PlayerController/BlasterPlayerController.h" -#include "Blaster/PlayerState/BlasterPlayerState.h" -#include "GameFramework/PlayerStart.h" #include "Kismet/GameplayStatics.h" - +#include "GameFramework/PlayerStart.h" +#include "Blaster/PlayerState/BlasterPlayerState.h" namespace MatchState { @@ -27,30 +25,30 @@ void ABlasterGameMode::BeginPlay() LevelStartingTime = GetWorld()->GetTimeSeconds(); } -void ABlasterGameMode::Tick(float DeltaSeconds) +void ABlasterGameMode::Tick(float DeltaTime) { - Super::Tick(DeltaSeconds); + Super::Tick(DeltaTime); if (MatchState == MatchState::WaitingToStart) { - CountDownTime = WarmupTime - GetWorld()->GetTimeSeconds() + LevelStartingTime; - if (CountDownTime <= 0.f) + CountdownTime = WarmupTime - GetWorld()->GetTimeSeconds() + LevelStartingTime; + if (CountdownTime <= 0.f) { StartMatch(); } } else if (MatchState == MatchState::InProgress) { - CountDownTime = WarmupTime + MatchTime - GetWorld()->GetTimeSeconds() + LevelStartingTime; - if (CountDownTime <= 0.f) + CountdownTime = WarmupTime + MatchTime - GetWorld()->GetTimeSeconds() + LevelStartingTime; + if (CountdownTime <= 0.f) { SetMatchState(MatchState::Cooldown); } } else if (MatchState == MatchState::Cooldown) { - CountDownTime = CooldownTime + WarmupTime + MatchTime - GetWorld()->GetTimeSeconds() + LevelStartingTime; - if (CountDownTime <= 0.f) + CountdownTime = CooldownTime + WarmupTime + MatchTime - GetWorld()->GetTimeSeconds() + LevelStartingTime; + if (CountdownTime <= 0.f) { RestartGame(); } @@ -61,29 +59,31 @@ void ABlasterGameMode::OnMatchStateSet() { Super::OnMatchStateSet(); - for (FConstPlayerControllerIterator Iterator = GetWorld()->GetPlayerControllerIterator(); Iterator; ++Iterator) + for (FConstPlayerControllerIterator It = GetWorld()->GetPlayerControllerIterator(); It; ++It) { - ABlasterPlayerController* PlayerController = Cast(*Iterator); - if (PlayerController) + ABlasterPlayerController* BlasterPlayer = Cast(*It); + if (BlasterPlayer) { - PlayerController->OnMatchStateSet(MatchState); + BlasterPlayer->OnMatchStateSet(MatchState); } } } -void ABlasterGameMode::PlayerEliminated(ABlasterCharacter* EliminatedCharacter, ABlasterPlayerController* VictimController, +void ABlasterGameMode::PlayerEliminated(class ABlasterCharacter* EliminatedCharacter, ABlasterPlayerController* VictimController, ABlasterPlayerController* AttackerController) { + if (AttackerController == nullptr || AttackerController->PlayerState == nullptr) return; + if (VictimController == nullptr || VictimController->PlayerState == nullptr) return; ABlasterPlayerState* AttackerPlayerState = AttackerController ? Cast(AttackerController->PlayerState) : nullptr; ABlasterPlayerState* VictimPlayerState = VictimController ? Cast(VictimController->PlayerState) : nullptr; if (AttackerPlayerState && AttackerPlayerState != VictimPlayerState) { - AttackerPlayerState->IncreaseScore(1.f); + AttackerPlayerState->AddToScore(1.f); } if (VictimPlayerState) { - VictimPlayerState->IncreaseDefeats(1); + VictimPlayerState->AddToDefeats(1); } if (EliminatedCharacter) @@ -99,12 +99,11 @@ void ABlasterGameMode::RequestRespawn(ACharacter* EliminatedCharacter, AControll EliminatedCharacter->Reset(); EliminatedCharacter->Destroy(); } - if (EliminatedController) { TArray PlayerStarts; UGameplayStatics::GetAllActorsOfClass(this, APlayerStart::StaticClass(), PlayerStarts); - const int32 Selection = FMath::RandRange(0, PlayerStarts.Num() - 1); + int32 Selection = FMath::RandRange(0, PlayerStarts.Num() - 1); RestartPlayerAtPlayerStart(EliminatedController, PlayerStarts[Selection]); } -} +} \ No newline at end of file diff --git a/Source/Blaster/GameMode/BlasterGameMode.h b/Source/Blaster/GameMode/BlasterGameMode.h index 1cf19f4..ff28489 100644 --- a/Source/Blaster/GameMode/BlasterGameMode.h +++ b/Source/Blaster/GameMode/BlasterGameMode.h @@ -22,7 +22,7 @@ class BLASTER_API ABlasterGameMode : public AGameMode public: ABlasterGameMode(); - virtual void Tick(float DeltaSeconds) override; + virtual void Tick(float DeltaTime) override; virtual void PlayerEliminated(class ABlasterCharacter* EliminatedCharacter, class ABlasterPlayerController* VictimController, class ABlasterPlayerController* AttackerController); virtual void RequestRespawn(ACharacter* EliminatedCharacter, AController* EliminatedController); @@ -43,8 +43,8 @@ protected: virtual void OnMatchStateSet() override; private: - float CountDownTime = 0.f; + float CountdownTime = 0.f; public: - FORCEINLINE float GetCountdownTime() const { return CountDownTime; } + FORCEINLINE float GetCountdownTime() const { return CountdownTime; } }; diff --git a/Source/Blaster/GameMode/LobbyGameMode.cpp b/Source/Blaster/GameMode/LobbyGameMode.cpp index 7328805..0adda8d 100644 --- a/Source/Blaster/GameMode/LobbyGameMode.cpp +++ b/Source/Blaster/GameMode/LobbyGameMode.cpp @@ -19,4 +19,4 @@ void ALobbyGameMode::PostLogin(APlayerController* NewPlayer) World->ServerTravel(FString("/Game/Maps/BlasterMap?listen")); } } -} +} \ No newline at end of file diff --git a/Source/Blaster/HUD/Announcement.h b/Source/Blaster/HUD/Announcement.h index 9f14d29..bff0230 100644 --- a/Source/Blaster/HUD/Announcement.h +++ b/Source/Blaster/HUD/Announcement.h @@ -13,16 +13,15 @@ UCLASS() class BLASTER_API UAnnouncement : public UUserWidget { GENERATED_BODY() - public: UPROPERTY(meta = (BindWidget)) - class UTextBlock* AnnouncementText; - + class UTextBlock* WarmupTime; + UPROPERTY(meta = (BindWidget)) - UTextBlock* CountdownText; - + UTextBlock* AnnouncementText; + UPROPERTY(meta = (BindWidget)) - UTextBlock* AnnouncementMessage; + UTextBlock* InfoText; }; diff --git a/Source/Blaster/HUD/BlasterHUD.cpp b/Source/Blaster/HUD/BlasterHUD.cpp index 9a7424a..3f9826c 100644 --- a/Source/Blaster/HUD/BlasterHUD.cpp +++ b/Source/Blaster/HUD/BlasterHUD.cpp @@ -22,7 +22,7 @@ void ABlasterHUD::AddCharacterOverlay() } } -void ABlasterHUD::AddAnnouncementOverlay() +void ABlasterHUD::AddAnnouncement() { APlayerController* PlayerController = GetOwningPlayerController(); if (PlayerController && AnnouncementClass) @@ -46,27 +46,27 @@ void ABlasterHUD::DrawHUD() if (HUDPackage.CrosshairsCenter) { const FVector2D Spread(0.f, 0.f); - DrawCrosshair(HUDPackage.CrosshairsCenter, ViewportCenter, Spread, HUDPackage.CrosshairColor); + DrawCrosshair(HUDPackage.CrosshairsCenter, ViewportCenter, Spread, HUDPackage.CrosshairsColor); } if (HUDPackage.CrosshairsLeft) { const FVector2D Spread(-SpreadScaled, 0.f); - DrawCrosshair(HUDPackage.CrosshairsLeft, ViewportCenter, Spread, HUDPackage.CrosshairColor); + DrawCrosshair(HUDPackage.CrosshairsLeft, ViewportCenter, Spread, HUDPackage.CrosshairsColor); } if (HUDPackage.CrosshairsRight) { const FVector2D Spread(SpreadScaled, 0.f); - DrawCrosshair(HUDPackage.CrosshairsRight, ViewportCenter, Spread, HUDPackage.CrosshairColor); + DrawCrosshair(HUDPackage.CrosshairsRight, ViewportCenter, Spread, HUDPackage.CrosshairsColor); } if (HUDPackage.CrosshairsTop) { const FVector2D Spread(0.f, -SpreadScaled); - DrawCrosshair(HUDPackage.CrosshairsTop, ViewportCenter, Spread, HUDPackage.CrosshairColor); + DrawCrosshair(HUDPackage.CrosshairsTop, ViewportCenter, Spread, HUDPackage.CrosshairsColor); } if (HUDPackage.CrosshairsBottom) { const FVector2D Spread(0.f, SpreadScaled); - DrawCrosshair(HUDPackage.CrosshairsBottom, ViewportCenter, Spread, HUDPackage.CrosshairColor); + DrawCrosshair(HUDPackage.CrosshairsBottom, ViewportCenter, Spread, HUDPackage.CrosshairsColor); } } } diff --git a/Source/Blaster/HUD/BlasterHUD.h b/Source/Blaster/HUD/BlasterHUD.h index 00e1e73..f803f11 100644 --- a/Source/Blaster/HUD/BlasterHUD.h +++ b/Source/Blaster/HUD/BlasterHUD.h @@ -18,7 +18,7 @@ public: UTexture2D* CrosshairsTop; UTexture2D* CrosshairsBottom; float CrosshairSpread; - FLinearColor CrosshairColor; + FLinearColor CrosshairsColor; }; /** @@ -32,7 +32,7 @@ class BLASTER_API ABlasterHUD : public AHUD public: virtual void DrawHUD() override; void AddCharacterOverlay(); - void AddAnnouncementOverlay(); + void AddAnnouncement(); UPROPERTY(EditAnywhere, Category = "Player Stats") TSubclassOf CharacterOverlayClass; diff --git a/Source/Blaster/Interfaces/InteractWithCrosshairInterface.cpp b/Source/Blaster/Interfaces/InteractWithCrosshairsInterface.cpp similarity index 81% rename from Source/Blaster/Interfaces/InteractWithCrosshairInterface.cpp rename to Source/Blaster/Interfaces/InteractWithCrosshairsInterface.cpp index 0b97038..144f424 100644 --- a/Source/Blaster/Interfaces/InteractWithCrosshairInterface.cpp +++ b/Source/Blaster/Interfaces/InteractWithCrosshairsInterface.cpp @@ -1,6 +1,6 @@ // Fill out your copyright notice in the Description page of Project Settings. -#include "InteractWithCrosshairInterface.h" +#include "InteractWithCrosshairsInterface.h" // Add default functionality here for any IInteractWithCrosshairInterface functions that are not pure virtual. diff --git a/Source/Blaster/Interfaces/InteractWithCrosshairInterface.h b/Source/Blaster/Interfaces/InteractWithCrosshairsInterface.h similarity index 70% rename from Source/Blaster/Interfaces/InteractWithCrosshairInterface.h rename to Source/Blaster/Interfaces/InteractWithCrosshairsInterface.h index 17d9211..d7a75a1 100644 --- a/Source/Blaster/Interfaces/InteractWithCrosshairInterface.h +++ b/Source/Blaster/Interfaces/InteractWithCrosshairsInterface.h @@ -4,11 +4,11 @@ #include "CoreMinimal.h" #include "UObject/Interface.h" -#include "InteractWithCrosshairInterface.generated.h" +#include "InteractWithCrosshairsInterface.generated.h" // This class does not need to be modified. UINTERFACE(MinimalAPI) -class UInteractWithCrosshairInterface : public UInterface +class UInteractWithCrosshairsInterface : public UInterface { GENERATED_BODY() }; @@ -16,7 +16,7 @@ class UInteractWithCrosshairInterface : public UInterface /** * */ -class BLASTER_API IInteractWithCrosshairInterface +class BLASTER_API IInteractWithCrosshairsInterface { GENERATED_BODY() diff --git a/Source/Blaster/PlayerController/BlasterPlayerController.cpp b/Source/Blaster/PlayerController/BlasterPlayerController.cpp index b3ac849..d71a128 100644 --- a/Source/Blaster/PlayerController/BlasterPlayerController.cpp +++ b/Source/Blaster/PlayerController/BlasterPlayerController.cpp @@ -2,7 +2,6 @@ #include "BlasterPlayerController.h" - #include "Blaster/Character/BlasterCharacter.h" #include "Blaster/Components/CombatComponent.h" #include "Blaster/GameMode/BlasterGameMode.h" @@ -31,38 +30,18 @@ void ABlasterPlayerController::GetLifetimeReplicatedProps(TArray(InPawn)) - { - SetHUDHealth(BlasterCharacter->GetHealth(), BlasterCharacter->GetMaxHealth()); - } -} - -void ABlasterPlayerController::ReceivedPlayer() -{ - Super::ReceivedPlayer(); - - if (IsLocalController()) - { - ServerRequestServerTime(GetWorld()->GetTimeSeconds()); - } -} - -void ABlasterPlayerController::CheckTimeSync(float DeltaSeconds) -{ - TimeSyncRunningTime += DeltaSeconds; + TimeSyncRunningTime += DeltaTime; if (IsLocalController() && TimeSyncRunningTime > TimeSyncFrequency) { ServerRequestServerTime(GetWorld()->GetTimeSeconds()); @@ -70,119 +49,172 @@ void ABlasterPlayerController::CheckTimeSync(float DeltaSeconds) } } -float ABlasterPlayerController::GetServerTime() -{ - if (HasAuthority()) return GetWorld()->GetTimeSeconds(); - return GetWorld()->GetTimeSeconds() + ClientServerDelta; -} - -void ABlasterPlayerController::HandleMatchHasStarted() -{ - BlasterHUD = BlasterHUD == nullptr ? Cast(GetHUD()) : BlasterHUD; - if (BlasterHUD) - { - BlasterHUD->AddCharacterOverlay(); - if (BlasterHUD->Announcement) - { - BlasterHUD->Announcement->SetVisibility(ESlateVisibility::Hidden); - } - } -} - -void ABlasterPlayerController::HandleCooldown() -{ - BlasterHUD = BlasterHUD == nullptr ? Cast(GetHUD()) : BlasterHUD; - if (BlasterHUD) - { - BlasterHUD->CharacterOverlay->RemoveFromParent(); - bool bHUDValid = - BlasterHUD->Announcement && - BlasterHUD->Announcement->AnnouncementText && - BlasterHUD->Announcement->AnnouncementMessage; - - if (bHUDValid) - { - const FString AnnouncementText("New match starts in:"); - BlasterHUD->Announcement->AnnouncementText->SetText(FText::FromString(AnnouncementText)); - BlasterHUD->Announcement->AnnouncementMessage->SetText(FText()); - BlasterHUD->Announcement->SetVisibility(ESlateVisibility::Visible); - } - } - - ABlasterCharacter* BlasterCharacter = Cast(GetPawn()); - if (BlasterCharacter && BlasterCharacter->GetCombat()) - { - BlasterCharacter->bDisableGameplay = true; - BlasterCharacter->GetCombat()->FireButtonPressed(false); - } -} - -void ABlasterPlayerController::OnMatchStateSet(FName State) -{ - MatchState = State; - - if (MatchState == MatchState::InProgress) - { - HandleMatchHasStarted(); - } - else if (MatchState == MatchState::Cooldown) - { - HandleCooldown(); - } -} - -void ABlasterPlayerController::OnRep_MatchState() -{ - if (MatchState == MatchState::InProgress) - { - HandleMatchHasStarted(); - } - else if (MatchState == MatchState::Cooldown) - { - HandleCooldown(); - } -} - void ABlasterPlayerController::ServerCheckMatchState_Implementation() { ABlasterGameMode* GameMode = Cast(UGameplayStatics::GetGameMode(this)); if (GameMode) { - LevelStartingTime = GameMode->LevelStartingTime; WarmupTime = GameMode->WarmupTime; MatchTime = GameMode->MatchTime; CooldownTime = GameMode->CooldownTime; + LevelStartingTime = GameMode->LevelStartingTime; MatchState = GameMode->GetMatchState(); - ClientJoinMidGame(MatchState, WarmupTime, MatchTime, CooldownTime, LevelStartingTime); + ClientJoinMidgame(MatchState, WarmupTime, MatchTime, CooldownTime, LevelStartingTime); } } -void ABlasterPlayerController::ClientJoinMidGame_Implementation(FName StateOfMatch, float Warmup, float Match, float Cooldown, float StartingTime) +void ABlasterPlayerController::ClientJoinMidgame_Implementation(FName StateOfMatch, float Warmup, float Match, float Cooldown, float StartingTime) { - LevelStartingTime = StartingTime; WarmupTime = Warmup; MatchTime = Match; CooldownTime = Cooldown; + LevelStartingTime = StartingTime; MatchState = StateOfMatch; OnMatchStateSet(MatchState); - if (BlasterHUD && MatchState == MatchState::WaitingToStart) { - BlasterHUD->AddAnnouncementOverlay(); + BlasterHUD->AddAnnouncement(); } } -void ABlasterPlayerController::ServerRequestServerTime_Implementation(float TimeOfClientRequest) +void ABlasterPlayerController::OnPossess(APawn* InPawn) { - const float ServerTimeOfReceipt = GetWorld()->GetTimeSeconds(); - ClientReportServerTime(TimeOfClientRequest, ServerTimeOfReceipt); + Super::OnPossess(InPawn); + ABlasterCharacter* BlasterCharacter = Cast(InPawn); + if (BlasterCharacter) + { + SetHUDHealth(BlasterCharacter->GetHealth(), BlasterCharacter->GetMaxHealth()); + } } -void ABlasterPlayerController::ClientReportServerTime_Implementation(float TimeOfClientRequest, float TimeServerReceivedClientRequest) +void ABlasterPlayerController::SetHUDHealth(float Health, float MaxHealth) { - const float RoundTripTime = GetWorld()->GetTimeSeconds() - TimeOfClientRequest; - const float CurrentServerTime = TimeServerReceivedClientRequest + (0.5f * RoundTripTime); - ClientServerDelta = CurrentServerTime - GetWorld()->GetTimeSeconds(); + BlasterHUD = BlasterHUD == nullptr ? Cast(GetHUD()) : BlasterHUD; + bool bHUDValid = BlasterHUD && + BlasterHUD->CharacterOverlay && + BlasterHUD->CharacterOverlay->HealthBar && + BlasterHUD->CharacterOverlay->HealthText; + if (bHUDValid) + { + const float HealthPercent = Health / MaxHealth; + BlasterHUD->CharacterOverlay->HealthBar->SetPercent(HealthPercent); + FString HealthText = FString::Printf(TEXT("%d/%d"), FMath::CeilToInt(Health), FMath::CeilToInt(MaxHealth)); + BlasterHUD->CharacterOverlay->HealthText->SetText(FText::FromString(HealthText)); + } + else + { + bInitializeCharacterOverlay = true; + HUDHealth = Health; + HUDMaxHealth = MaxHealth; + } +} + +void ABlasterPlayerController::SetHUDScore(float Score) +{ + BlasterHUD = BlasterHUD == nullptr ? Cast(GetHUD()) : BlasterHUD; + bool bHUDValid = BlasterHUD && + BlasterHUD->CharacterOverlay && + BlasterHUD->CharacterOverlay->ScoreValue; + + if (bHUDValid) + { + FString ScoreText = FString::Printf(TEXT("%d"), FMath::FloorToInt(Score)); + BlasterHUD->CharacterOverlay->ScoreValue->SetText(FText::FromString(ScoreText)); + } + else + { + bInitializeCharacterOverlay = true; + HUDScore = Score; + } +} + +void ABlasterPlayerController::SetHUDDefeats(int32 Defeats) +{ + BlasterHUD = BlasterHUD == nullptr ? Cast(GetHUD()) : BlasterHUD; + bool bHUDValid = BlasterHUD && + BlasterHUD->CharacterOverlay && + BlasterHUD->CharacterOverlay->DefeatsValue; + if (bHUDValid) + { + FString DefeatsText = FString::Printf(TEXT("%d"), Defeats); + BlasterHUD->CharacterOverlay->DefeatsValue->SetText(FText::FromString(DefeatsText)); + } + else + { + bInitializeCharacterOverlay = true; + HUDDefeats = Defeats; + } +} + +void ABlasterPlayerController::SetHUDWeaponAmmo(int32 Ammo) +{ + BlasterHUD = BlasterHUD == nullptr ? Cast(GetHUD()) : BlasterHUD; + bool bHUDValid = BlasterHUD && + BlasterHUD->CharacterOverlay && + BlasterHUD->CharacterOverlay->WeaponAmmoValue; + + if (bHUDValid) + { + FString AmmoText = FString::Printf(TEXT("%d"), Ammo); + BlasterHUD->CharacterOverlay->WeaponAmmoValue->SetText(FText::FromString(AmmoText)); + } +} + +void ABlasterPlayerController::SetHUDCarriedAmmo(int32 Ammo) +{ + BlasterHUD = BlasterHUD == nullptr ? Cast(GetHUD()) : BlasterHUD; + bool bHUDValid = BlasterHUD && + BlasterHUD->CharacterOverlay && + BlasterHUD->CharacterOverlay->CarriedAmmoValue; + if (bHUDValid) + { + FString AmmoText = FString::Printf(TEXT("%d"), Ammo); + BlasterHUD->CharacterOverlay->CarriedAmmoValue->SetText(FText::FromString(AmmoText)); + } +} + +void ABlasterPlayerController::SetHUDMatchCountdown(float CountdownTime) +{ + BlasterHUD = BlasterHUD == nullptr ? Cast(GetHUD()) : BlasterHUD; + bool bHUDValid = BlasterHUD && + BlasterHUD->CharacterOverlay && + BlasterHUD->CharacterOverlay->MatchCountdownText; + if (bHUDValid) + { + if (CountdownTime < 0.f) + { + BlasterHUD->CharacterOverlay->MatchCountdownText->SetText(FText()); + return; + } + + int32 Minutes = FMath::FloorToInt(CountdownTime / 60.f); + int32 Seconds = CountdownTime - Minutes * 60; + + FString CountdownText = FString::Printf(TEXT("%02d:%02d"), Minutes, Seconds); + BlasterHUD->CharacterOverlay->MatchCountdownText->SetText(FText::FromString(CountdownText)); + } +} + +void ABlasterPlayerController::SetHUDAnnouncementCountdown(float CountdownTime) +{ + BlasterHUD = BlasterHUD == nullptr ? Cast(GetHUD()) : BlasterHUD; + bool bHUDValid = BlasterHUD && + BlasterHUD->Announcement && + BlasterHUD->Announcement->WarmupTime; + if (bHUDValid) + { + if (CountdownTime < 0.f) + { + BlasterHUD->Announcement->WarmupTime->SetText(FText()); + return; + } + + int32 Minutes = FMath::FloorToInt(CountdownTime / 60.f); + int32 Seconds = CountdownTime - Minutes * 60; + + FString CountdownText = FString::Printf(TEXT("%02d:%02d"), Minutes, Seconds); + BlasterHUD->Announcement->WarmupTime->SetText(FText::FromString(CountdownText)); + } } void ABlasterPlayerController::SetHUDTime() @@ -225,142 +257,95 @@ void ABlasterPlayerController::PollInit() } } -void ABlasterPlayerController::SetHUDHealth(float Health, float MaxHealth) +void ABlasterPlayerController::ServerRequestServerTime_Implementation(float TimeOfClientRequest) { - BlasterHUD = BlasterHUD == nullptr ? Cast(GetHUD()) : BlasterHUD; - bool bHUDValid = - BlasterHUD && - BlasterHUD->CharacterOverlay && - BlasterHUD->CharacterOverlay->HealthBar && - BlasterHUD->CharacterOverlay->HealthText; + float ServerTimeOfReceipt = GetWorld()->GetTimeSeconds(); + ClientReportServerTime(TimeOfClientRequest, ServerTimeOfReceipt); +} - if (bHUDValid) +void ABlasterPlayerController::ClientReportServerTime_Implementation(float TimeOfClientRequest, float TimeServerReceivedClientRequest) +{ + float RoundTripTime = GetWorld()->GetTimeSeconds() - TimeOfClientRequest; + float CurrentServerTime = TimeServerReceivedClientRequest + (0.5f * RoundTripTime); + ClientServerDelta = CurrentServerTime - GetWorld()->GetTimeSeconds(); +} + +float ABlasterPlayerController::GetServerTime() +{ + if (HasAuthority()) return GetWorld()->GetTimeSeconds(); + return GetWorld()->GetTimeSeconds() + ClientServerDelta; +} + +void ABlasterPlayerController::ReceivedPlayer() +{ + Super::ReceivedPlayer(); + if (IsLocalController()) { - const float HealthPercent = Health / MaxHealth; - BlasterHUD->CharacterOverlay->HealthBar->SetPercent(HealthPercent); - const FString HealthText = FString::Printf(TEXT("%d/%d"), FMath::CeilToInt(Health), FMath::CeilToInt(MaxHealth)); - BlasterHUD->CharacterOverlay->HealthText->SetText(FText::FromString(HealthText)); - } - else - { - bInitializeCharacterOverlay = true; - HUDHealth = Health; - HUDMaxHealth = MaxHealth; + ServerRequestServerTime(GetWorld()->GetTimeSeconds()); } } -void ABlasterPlayerController::SetHUDScore(float Score) +void ABlasterPlayerController::OnMatchStateSet(FName State) { - BlasterHUD = BlasterHUD == nullptr ? Cast(GetHUD()) : BlasterHUD; - bool bHUDValid = - BlasterHUD && - BlasterHUD->CharacterOverlay && - BlasterHUD->CharacterOverlay->ScoreValue; + MatchState = State; - if (bHUDValid) + if (MatchState == MatchState::InProgress) { - const FString ScoreAmount = FString::Printf(TEXT("%d"), FMath::FloorToInt(Score)); - BlasterHUD->CharacterOverlay->ScoreValue->SetText(FText::FromString(ScoreAmount)); + HandleMatchHasStarted(); } - else + else if (MatchState == MatchState::Cooldown) { - bInitializeCharacterOverlay = true; - HUDScore = Score; + HandleCooldown(); } } -void ABlasterPlayerController::SetHUDDefeats(int32 Defeats) +void ABlasterPlayerController::OnRep_MatchState() { - BlasterHUD = BlasterHUD == nullptr ? Cast(GetHUD()) : BlasterHUD; - bool bHUDValid = - BlasterHUD && - BlasterHUD->CharacterOverlay && - BlasterHUD->CharacterOverlay->DefeatsValue; - - if (bHUDValid) + if (MatchState == MatchState::InProgress) { - const FString DefeatsAmount = FString::Printf(TEXT("%d"), Defeats); - BlasterHUD->CharacterOverlay->DefeatsValue->SetText(FText::FromString(DefeatsAmount)); + HandleMatchHasStarted(); } - else + else if (MatchState == MatchState::Cooldown) { - bInitializeCharacterOverlay = true; - HUDDefeats = Defeats; + HandleCooldown(); } } -void ABlasterPlayerController::SetHUDWeaponAmmo(int32 Ammo) +void ABlasterPlayerController::HandleMatchHasStarted() { BlasterHUD = BlasterHUD == nullptr ? Cast(GetHUD()) : BlasterHUD; - bool bHUDValid = - BlasterHUD && - BlasterHUD->CharacterOverlay && - BlasterHUD->CharacterOverlay->WeaponAmmoValue; - - if (bHUDValid) + if (BlasterHUD) { - const FString WeaponAmmoAmount = FString::Printf(TEXT("%d"), Ammo); - BlasterHUD->CharacterOverlay->WeaponAmmoValue->SetText(FText::FromString(WeaponAmmoAmount)); - } -} - -void ABlasterPlayerController::SetHUDCarriedAmmo(int32 Ammo) -{ - BlasterHUD = BlasterHUD == nullptr ? Cast(GetHUD()) : BlasterHUD; - bool bHUDValid = - BlasterHUD && - BlasterHUD->CharacterOverlay && - BlasterHUD->CharacterOverlay->CarriedAmmoValue; - - if (bHUDValid) - { - const FString CarriedAmmoAmount = FString::Printf(TEXT("%d"), Ammo); - BlasterHUD->CharacterOverlay->CarriedAmmoValue->SetText(FText::FromString(CarriedAmmoAmount)); - } -} - -void ABlasterPlayerController::SetHUDMatchCountdown(float CountdownTime) -{ - BlasterHUD = BlasterHUD == nullptr ? Cast(GetHUD()) : BlasterHUD; - bool bHUDValid = - BlasterHUD && - BlasterHUD->CharacterOverlay && - BlasterHUD->CharacterOverlay->MatchCountdownText; - - if (bHUDValid) - { - if (CountdownTime < 0.f) + BlasterHUD->AddCharacterOverlay(); + if (BlasterHUD->Announcement) { - BlasterHUD->CharacterOverlay->MatchCountdownText->SetText(FText()); - return; + BlasterHUD->Announcement->SetVisibility(ESlateVisibility::Hidden); } - const int32 Minutes = FMath::FloorToInt(CountdownTime / 60); - const int32 Seconds = CountdownTime - Minutes * 60; - - const FString CountdownText = FString::Printf(TEXT("%02d:%02d"), Minutes, Seconds); - BlasterHUD->CharacterOverlay->MatchCountdownText->SetText(FText::FromString(CountdownText)); } } -void ABlasterPlayerController::SetHUDAnnouncementCountdown(float CountdownTime) +void ABlasterPlayerController::HandleCooldown() { BlasterHUD = BlasterHUD == nullptr ? Cast(GetHUD()) : BlasterHUD; - bool bHUDValid = - BlasterHUD && - BlasterHUD->Announcement && - BlasterHUD->Announcement->CountdownText; - - if (bHUDValid) + if (BlasterHUD) { - if (CountdownTime < 0.f) - { - BlasterHUD->Announcement->CountdownText->SetText(FText()); - return; - } - const int32 Minutes = FMath::FloorToInt(CountdownTime / 60); - const int32 Seconds = CountdownTime - Minutes * 60; + BlasterHUD->CharacterOverlay->RemoveFromParent(); + bool bHUDValid = BlasterHUD->Announcement && + BlasterHUD->Announcement->AnnouncementText && + BlasterHUD->Announcement->InfoText; - const FString CountdownText = FString::Printf(TEXT("%02d:%02d"), Minutes, Seconds); - BlasterHUD->Announcement->CountdownText->SetText(FText::FromString(CountdownText)); + if (bHUDValid) + { + BlasterHUD->Announcement->SetVisibility(ESlateVisibility::Visible); + FString AnnouncementText("New match starts in:"); + BlasterHUD->Announcement->AnnouncementText->SetText(FText::FromString(AnnouncementText)); + BlasterHUD->Announcement->InfoText->SetText(FText()); + } + } + ABlasterCharacter* BlasterCharacter = Cast(GetPawn()); + if (BlasterCharacter && BlasterCharacter->GetCombat()) + { + BlasterCharacter->bDisableGameplay = true; + BlasterCharacter->GetCombat()->FireButtonPressed(false); } } diff --git a/Source/Blaster/PlayerController/BlasterPlayerController.h b/Source/Blaster/PlayerController/BlasterPlayerController.h index 7d00814..25957b2 100644 --- a/Source/Blaster/PlayerController/BlasterPlayerController.h +++ b/Source/Blaster/PlayerController/BlasterPlayerController.h @@ -15,7 +15,7 @@ class BLASTER_API ABlasterPlayerController : public APlayerController GENERATED_BODY() public: - virtual void Tick(float DeltaSeconds) override; + virtual void Tick(float DeltaTime) override; virtual void OnPossess(APawn* InPawn) override; virtual void ReceivedPlayer() override; // Sync with server clock as soon as possible virtual void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override; @@ -63,7 +63,7 @@ protected: void ServerCheckMatchState(); UFUNCTION(Client, Reliable) - void ClientJoinMidGame(FName StateOfMatch, float Warmup, float Match, float Cooldown, float StartingTime); + void ClientJoinMidgame(FName StateOfMatch, float Warmup, float Match, float Cooldown, float StartingTime); private: UPROPERTY() diff --git a/Source/Blaster/PlayerState/BlasterPlayerState.cpp b/Source/Blaster/PlayerState/BlasterPlayerState.cpp index b09d7f4..9c556a9 100644 --- a/Source/Blaster/PlayerState/BlasterPlayerState.cpp +++ b/Source/Blaster/PlayerState/BlasterPlayerState.cpp @@ -7,21 +7,6 @@ #include "Blaster/PlayerController/BlasterPlayerController.h" #include "Net/UnrealNetwork.h" -void ABlasterPlayerState::IncreaseScore(float ScoreAmount) -{ - SetScore(GetScore() + ScoreAmount); - - Character = GetCharacter(); - if (Character) - { - Controller = GetController(); - if (Controller) - { - Controller->SetHUDScore(GetScore()); - } - } -} - void ABlasterPlayerState::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); @@ -29,14 +14,13 @@ void ABlasterPlayerState::GetLifetimeReplicatedProps(TArray& DOREPLIFETIME(ABlasterPlayerState, Defeats); } -void ABlasterPlayerState::OnRep_Score() +void ABlasterPlayerState::AddToScore(float ScoreAmount) { - Super::OnRep_Score(); - - Character = GetCharacter(); + SetScore(GetScore() + ScoreAmount); + Character = Character == nullptr ? Cast(GetPawn()) : Character; if (Character) { - Controller = GetController(); + Controller = Controller == nullptr ? Cast(Character->Controller) : Controller; if (Controller) { Controller->SetHUDScore(GetScore()); @@ -44,14 +28,28 @@ void ABlasterPlayerState::OnRep_Score() } } -void ABlasterPlayerState::IncreaseDefeats(int32 DefeatsAmount) +void ABlasterPlayerState::OnRep_Score() { - Defeats += DefeatsAmount; + Super::OnRep_Score(); - Character = GetCharacter(); + Character = Character == nullptr ? Cast(GetPawn()) : Character; if (Character) { - Controller = GetController(); + Controller = Controller == nullptr ? Cast(Character->Controller) : Controller; + if (Controller) + { + Controller->SetHUDScore(GetScore()); + } + } +} + +void ABlasterPlayerState::AddToDefeats(int32 DefeatsAmount) +{ + Defeats += DefeatsAmount; + Character = Character == nullptr ? Cast(GetPawn()) : Character; + if (Character) + { + Controller = Controller == nullptr ? Cast(Character->Controller) : Controller; if (Controller) { Controller->SetHUDDefeats(Defeats); @@ -61,29 +59,13 @@ void ABlasterPlayerState::IncreaseDefeats(int32 DefeatsAmount) void ABlasterPlayerState::OnRep_Defeats() { - Character = GetCharacter(); + Character = Character == nullptr ? Cast(GetPawn()) : Character; if (Character) { - Controller = GetController(); + Controller = Controller == nullptr ? Cast(Character->Controller) : Controller; if (Controller) { Controller->SetHUDDefeats(Defeats); } } } - -ABlasterCharacter* ABlasterPlayerState::GetCharacter() const -{ - return Character == nullptr ? Cast(GetPawn()) : Character; -} - -ABlasterPlayerController* ABlasterPlayerState::GetController() const -{ - if (Character) - { - return Controller == nullptr ? Cast(Character->Controller) : Controller; - } - - return nullptr; -} - diff --git a/Source/Blaster/PlayerState/BlasterPlayerState.h b/Source/Blaster/PlayerState/BlasterPlayerState.h index 20b3fa6..e4a8c10 100644 --- a/Source/Blaster/PlayerState/BlasterPlayerState.h +++ b/Source/Blaster/PlayerState/BlasterPlayerState.h @@ -17,19 +17,18 @@ class BLASTER_API ABlasterPlayerState : public APlayerState public: virtual void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override; virtual void OnRep_Score() override; + UFUNCTION() virtual void OnRep_Defeats(); - void IncreaseScore(float ScoreAmount); - void IncreaseDefeats(int32 DefeatsAmount); + void AddToScore(float ScoreAmount); + void AddToDefeats(int32 DefeatsAmount); private: UPROPERTY() class ABlasterCharacter* Character; UPROPERTY() class ABlasterPlayerController* Controller; - ABlasterCharacter* GetCharacter() const; - ABlasterPlayerController* GetController() const; UPROPERTY(ReplicatedUsing = OnRep_Defeats) int32 Defeats; diff --git a/Source/Blaster/Types/CombatState.h b/Source/Blaster/Types/CombatState.h index 0a82ac1..0f434a6 100644 --- a/Source/Blaster/Types/CombatState.h +++ b/Source/Blaster/Types/CombatState.h @@ -5,6 +5,6 @@ enum class ECombatState : uint8 { ECS_Unoccupied UMETA(DisplayName = "Unoccupied"), ECS_Reloading UMETA(DisplayName = "Reloading"), - + ECS_MAX UMETA(DisplayName = "DefaultMAX") -}; +}; \ No newline at end of file