From f20cb6c8805364fdeee03ee5483733a4f956223f Mon Sep 17 00:00:00 2001 From: Alexei Gladkikh Date: Fri, 10 May 2024 12:41:13 +0300 Subject: [PATCH] #204 #155 Fixed infinity ammo reload bug and shotgun reload animation bug --- .../Weapon/Classes/Cloud9WeaponBase.cpp | 17 ++++--- .../Cloud9/Weapon/Classes/Cloud9WeaponBase.h | 1 + .../Weapon/Classes/Cloud9WeaponFirearm.cpp | 45 ++++++++++++------- .../Weapon/Classes/Cloud9WeaponFirearm.h | 19 +++++--- 4 files changed, 54 insertions(+), 28 deletions(-) diff --git a/Source/Cloud9/Weapon/Classes/Cloud9WeaponBase.cpp b/Source/Cloud9/Weapon/Classes/Cloud9WeaponBase.cpp index 73a787a9b..faf4f93b8 100644 --- a/Source/Cloud9/Weapon/Classes/Cloud9WeaponBase.cpp +++ b/Source/Cloud9/Weapon/Classes/Cloud9WeaponBase.cpp @@ -420,13 +420,18 @@ void ACloud9WeaponBase::SecondaryAction(bool IsReleased) WeaponState.ActivateAction(EWeaponAction::Secondary, IsReleased); } +bool ACloud9WeaponBase::CanReload() const { return false; } + void ACloud9WeaponBase::Reload(bool IsReleased) { - WeaponState.ActivateSequence( - EWeaponAction::ReloadStart, - EWeaponAction::ReloadLoop, - EWeaponAction::ReloadEnd, - IsReleased); + if (CanReload()) + { + WeaponState.ActivateSequence( + EWeaponAction::ReloadStart, + EWeaponAction::ReloadLoop, + EWeaponAction::ReloadEnd, + IsReleased); + } } bool ACloud9WeaponBase::Initialize(const FWeaponConfig& WeaponConfig) @@ -441,7 +446,7 @@ bool ACloud9WeaponBase::Initialize(const FWeaponConfig& WeaponConfig) return false; } - // Enable tick only when weapon armed + // Enable tick only when a weapon armed SetActorTickEnabled(false); return true; diff --git a/Source/Cloud9/Weapon/Classes/Cloud9WeaponBase.h b/Source/Cloud9/Weapon/Classes/Cloud9WeaponBase.h index 96cad9322..01ca58cff 100644 --- a/Source/Cloud9/Weapon/Classes/Cloud9WeaponBase.h +++ b/Source/Cloud9/Weapon/Classes/Cloud9WeaponBase.h @@ -198,6 +198,7 @@ class CLOUD9_API ACloud9WeaponBase : public AActor virtual void PrimaryAction(bool IsReleased); virtual void SecondaryAction(bool IsReleased); + virtual bool CanReload() const; virtual void Reload(bool IsReleased); USceneComponent* GetShootLocationActor() const; diff --git a/Source/Cloud9/Weapon/Classes/Cloud9WeaponFirearm.cpp b/Source/Cloud9/Weapon/Classes/Cloud9WeaponFirearm.cpp index f17df3bfc..6c4343d4b 100644 --- a/Source/Cloud9/Weapon/Classes/Cloud9WeaponFirearm.cpp +++ b/Source/Cloud9/Weapon/Classes/Cloud9WeaponFirearm.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2023 Alexei Gladkikh +// Copyright (c) 2023 Alexei Gladkikh // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -46,7 +46,6 @@ #include "Cloud9/Tools/Math.h" #include "Cloud9/Tools/Structures.h" #include "Cloud9/Tools/Extensions/TArray.h" -#include "Cloud9/Tools/Extensions/USoundBase.h" #include "Cloud9/Weapon/Sounds/Cloud9SoundPlayer.h" #include "Cloud9/Weapon/Structures/WeaponConfig.h" #include "Cloud9/Weapon/Tables/WeaponTableFirearm.h" @@ -59,7 +58,6 @@ const FName ACloud9WeaponFirearm::TracerDirectionParameterName = TEXT("Direction TErrorValue FCursorHitScanInfo::Create( const ACloud9WeaponFirearm* Firearm, - const FFirearmWeaponInfo* WeaponInfo, const FFirearmCommonData& FirearmCommonData) { static let Settings = UCloud9DeveloperSettings::Get(); @@ -226,7 +224,7 @@ void ACloud9WeaponFirearm::Tick(float DeltaSeconds) WEAPON_IS_ACTION_IN_PROGRESS_GUARD(); - let Character = GetOwner(); // suppose weapon has owner cus we pass bond guard + let Character = GetOwner(); // suppose a weapon has owner cus we pass bond guard let AnimComponent = Character->GetAnimationComponent(); WEAPON_ANIM_COMPONENT_GUARD(); @@ -263,15 +261,24 @@ void ACloud9WeaponFirearm::Tick(float DeltaSeconds) { if (WeaponState.IsActionActive(EWeaponAction::ReloadLoop)) { - ExecuteAction( - EWeaponAction::ReloadLoop, - WeaponInfo->ReloadLoopTime, - [&] - { - return UpdateReloadAmmo(WeaponInfo->Type == EWeaponType::Shotgun) - and AnimComponent->PlayMontage(PoseMontages->ReloadLoopMontage); - } - ); + // Assume only shotguns has looped reload + if (not CanReload()) + { + WeaponState.ClearAction(EWeaponAction::ReloadLoop); + WeaponState.ActivateAction(EWeaponAction::ReloadEnd); + } + else + { + ExecuteAction( + EWeaponAction::ReloadLoop, + WeaponInfo->ReloadLoopTime, + [&] + { + return UpdateReloadAmmo(true) and + AnimComponent->PlayMontage(PoseMontages->ReloadLoopMontage); + } + ); + } } else if (WeaponState.IsActionActive(EWeaponAction::ReloadEnd)) { @@ -304,8 +311,14 @@ void ACloud9WeaponFirearm::Tick(float DeltaSeconds) WeaponInfo->CycleTime, [&] { - if (let Status = PrimaryAttack(WeaponInfo, CommonData->Firearm); - Status > EFirearmFireStatus::PlayAnimation) + let Status = PrimaryAttack(WeaponInfo, CommonData->Firearm); + + if (Status == EFirearmFireStatus::OutOfAmmo) + { + return true; + } + + if (Status == EFirearmFireStatus::Error) { log(Error, "[Weapon='%s'] Weapon fire failure status = %d", *GetName(), Status); return false; @@ -381,7 +394,7 @@ EFirearmFireStatus ACloud9WeaponFirearm::PrimaryAttack( return EFirearmFireStatus::OutOfAmmo; } - if (var [Error, HitScanInfo] = FCursorHitScanInfo::Create(this, WeaponInfo, FirearmCommonData); + if (var [Error, HitScanInfo] = FCursorHitScanInfo::Create(this, FirearmCommonData); Error == EFirearmFireStatus::Success) { let EndLocations = RecalculateByShotInaccuracy(*HitScanInfo); diff --git a/Source/Cloud9/Weapon/Classes/Cloud9WeaponFirearm.h b/Source/Cloud9/Weapon/Classes/Cloud9WeaponFirearm.h index 91141ecb9..66aa76056 100644 --- a/Source/Cloud9/Weapon/Classes/Cloud9WeaponFirearm.h +++ b/Source/Cloud9/Weapon/Classes/Cloud9WeaponFirearm.h @@ -24,6 +24,8 @@ #pragma once #include "CoreMinimal.h" +#include "Cloud9/Character/Components/Cloud9HealthComponent.h" +#include "Cloud9/Physicals/Cloud9PhysicalMaterial.h" #include "Cloud9/Tools/Structures.h" #include "Cloud9/Weapon/Classes/Cloud9WeaponBase.h" @@ -46,10 +48,8 @@ enum class EFirearmFireStatus : uint8 { Success = 0, NoCursorHit = 1, - - PlayAnimation = NoCursorHit, - OutOfAmmo = 2, + Error = 0x80 }; @@ -71,7 +71,6 @@ struct FCursorHitScanInfo static TErrorValue Create( const ACloud9WeaponFirearm* Firearm, - const FFirearmWeaponInfo* WeaponInfo, const FFirearmCommonData& FirearmCommonData); }; @@ -103,7 +102,6 @@ class CLOUD9_API ACloud9WeaponFirearm : public ACloud9WeaponBase static constexpr let ArmorCoefficient = 0.5f; static constexpr let ArmorBonus = 0.5f; -public: virtual FWeaponId GetWeaponId() const override; template @@ -130,6 +128,10 @@ class CLOUD9_API ACloud9WeaponFirearm : public ACloud9WeaponBase const FFirearmCommonData& FirearmCommonData, const FCursorHitScanInfo& HitScanInfo); + bool HasAmmoInReserve() const; + bool IsFullyLoaded() const; + virtual bool CanReload() const override; + bool UpdateReloadAmmo(bool IsShotgun); float GetInaccuracy() const; @@ -141,7 +143,12 @@ class CLOUD9_API ACloud9WeaponFirearm : public ACloud9WeaponBase void DropMagazine() const; void EjectCase() const; -protected: // properties + static USoundBase* GetHitSound( + AActor* DamagedActor, + const UCloud9PhysicalMaterial* DamagedPhysicalMaterial, + const UCloud9HealthComponent* DamagedHealthComponent, + FName Bone); + UPROPERTY(BlueprintAssignable, meta=(AllowPrivateAccess), Category=Events) FOnAmmoInReserveChanged OnAmmoInReserveChanged;