From 0f2fac10bd2743ff031116c0a2c57252c44712fc Mon Sep 17 00:00:00 2001 From: Kubson96 <42842162+Kubson96@users.noreply.github.com> Date: Sat, 22 Feb 2025 01:28:07 +0100 Subject: [PATCH] feat: add recoil, fire rate and reloading Added recoil force while shooting Added fire rate system Implement reloading --- .../Player/BP_ExoPlayerCharacter.uasset | Bin 25331 -> 26680 bytes .../Components/ShootingComponent.cpp | 45 +++++++++++++++--- .../Private/Player/ExoPlayerController.cpp | 3 +- .../Characters/Components/ShootingComponent.h | 38 ++++++++++++++- 4 files changed, 75 insertions(+), 11 deletions(-) diff --git a/Content/Blueprints/Characters/Player/BP_ExoPlayerCharacter.uasset b/Content/Blueprints/Characters/Player/BP_ExoPlayerCharacter.uasset index 4ba0aa784507c5790afe9742d8c0a50ee7886282..3b8aa071137cadf6dafd88551569701fb6364c40 100644 GIT binary patch delta 7468 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 delta 6321 zcmd5=eQZ?65#MLd#vfpx@%heo*gk{7V8_rLU}(UA%^9!_#$X#_Z1DGm7+jm$PTGVt zr!=8$J`|FyDpjhQ;2ZnQA0~xnt)4{L_o0GNbdah?HupE zd@fR|j(l%-XMQ^~yE8j)pHE*fuAeo2TwM3&2^D=>osa=yT#DGT#gZh`Ky+S|RLLoAz|2VPE_w!w+H~jt&zLyu=_e$ybpVqzp zeDkUKYn|=yX8##@=n2XXjMl|RX~r-5XlS8nqMSM*x`_8$pBzZ(lJBM*4t35+og>H6 zn&by*H$tiDV@BvF8Apv!OV*1i(#SrQn?dkae{1)yk%55l{qD`P@_Kenx?L-ly;%!^ zP-K_gInH2@9@%tzmF)KGeywiN^yoe?8 z*$skUvrM_qL zvLh7@@`XNo>!aUuAk1=Fu!*WW=?ec0-Wy&>=bQP~p zo1zV$_J{5*zUq}7)t5s{HorR8T}(5+a%OrHW`a`9M);+%-4XFRfM7dIb*n=z1P%xs z0#%ufI)ghg7N=CYc6a3jJD;MCmS5AkxU@E$VL&;3&iVTk9}CJoNlmpu|}X~ z47U}?l@&R{LEHlkM209)fj6k1C(k!7tq9MYqF~U3&lsOYg(@22C2dR^m!CL)t_fAK~PE(|1SU;#u zUffwxW%bY62O@gB8%!d<{HVz>P^0>{4-bcsomXeVT4vxTC^j4JHU$Z?;nz*}e5)%F zZXBr5bLZ%mPkY!6g9IohcVfPG*Yc%S)62CHPTOsId=Jt#_*p$-(;NkHi;`oV7IMj8 zKSiS!u$>$|j@~9ilxj(tZdt_=b4=xQsg|I)fns&=oLI?5a|-3f8@um!Z_*=PDMwcw z(59zo?sx8m`(%IEhv z z6u1W7?s8Q6voF51|8H-K=AWitn0t8Nnf!RXq=8eK4j!94zT@F%o4-8z^%vfr{Pr+3 zMf2(?1*#WsF?TXt#E?#!Wj3E~M(l_(e+LFG7RC6Ex|@>APCJ~FCwH9r^_9qK*G>Oz@)t%l)}U+dnopaf_l zXl@(qKf)N9*5hA*+yaHS!X=k=oiIw|&$_$@`(|`Mnu=Z6CUXWVgSl!#y!ULamT*&` zJ27{I52-G>6AAH_#=mkw`^+Z%j;HS$c`{Jy?$mrv?ua+F%nsOtYcwL}>cO8eR%a7B zid%0&N3W1Dk)!fkfwClC-k8ZtzLC$$OI+m>dWn6wb1ygjtMZd6+qsL|z8`WtllzT} zT?zM(GetOwner()); } void UShootingComponent::Shoot() { - AActor* Owner = GetOwner(); + if (CurrentAmmo == 0 || bIsReloading || !bCanShoot) return; - FVector LineStart = Owner->GetActorLocation(); - FVector ForwardVector = Owner->GetActorForwardVector(); + bCanShoot = false; + CurrentAmmo--; + + FVector LineStart = PlayerCharacter->GetActorLocation(); + FVector ForwardVector = PlayerCharacter->GetActorForwardVector(); FVector LineEnd = LineStart + (ForwardVector * MaxRange); FHitResult HitResult; FCollisionQueryParams QueryParams; - QueryParams.AddIgnoredActor(Owner); + QueryParams.AddIgnoredActor(PlayerCharacter); + // Strzał bool bHit = GetWorld()->LineTraceSingleByChannel(HitResult, LineStart, LineEnd, ECC_Visibility, QueryParams); if (bHit && HitResult.GetActor() && HitResult.GetActor()->Implements()) { IDamageable::Execute_TakeDamage(HitResult.GetActor(), DamageValue); - UE_LOG(LogTemp, Warning, TEXT("Shoot")); + UE_LOG(LogTemp, Display, TEXT("Shoot. Ammo: %d/%d"), CurrentAmmo, MaxAmmo); // Docelowo tutaj wywołanie UI aktualizujące stan ammo } + PlayerCharacter->GetWorldTimerManager().SetTimer(ShootCooldownTimer, this, &UShootingComponent::ResetFireCooldown, FireRateCooldown, false); + + // Odrzut + FVector RecoilDirection = -PlayerCharacter->GetActorForwardVector(); + PlayerCharacter->LaunchCharacter(RecoilDirection * RecoilForce, true, false); + + // DEBUG if (bShowDebugLine) DrawDebugLine(GetWorld(), LineStart, LineEnd, FColor::Red, false, 1.0f, 0, 1.0f); } +void UShootingComponent::Reload() +{ + if (bIsReloading) return; + + bIsReloading = true; + + CurrentAmmo = MaxAmmo; + PlayerCharacter->GetWorldTimerManager().SetTimer(ReloadTimer, this, &UShootingComponent::ReloadCompleted, ReloadTime, false); + + UE_LOG(LogTemp, Display, TEXT("Reloaded. Ammo: %d/%d"), CurrentAmmo, MaxAmmo); // Docelowo tutaj wywołanie UI aktualizujące stan ammo +} + +void UShootingComponent::ResetFireCooldown() +{ + bCanShoot = true; +} + +void UShootingComponent::ReloadCompleted() +{ + bIsReloading = false; +} // Called every frame void UShootingComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) diff --git a/Source/Exo/Private/Player/ExoPlayerController.cpp b/Source/Exo/Private/Player/ExoPlayerController.cpp index 68803ed..f8822d0 100644 --- a/Source/Exo/Private/Player/ExoPlayerController.cpp +++ b/Source/Exo/Private/Player/ExoPlayerController.cpp @@ -48,7 +48,6 @@ void AExoPlayerController::SetupInputComponent() EnhancedInputComponent->BindAction(InteractAction, ETriggerEvent::Triggered, this, &AExoPlayerController::Interact); EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerJump); EnhancedInputComponent->BindAction(DodgeAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerDodge); - //EnhancedInputComponent->BindAction(, ETriggerEvent::Started, this, &AExoPlayerController::ResetDodge); EnhancedInputComponent->BindAction(CrouchAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerCrouch); EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerSprint); EnhancedInputComponent->BindAction(ShootAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerShoot); @@ -152,5 +151,5 @@ void AExoPlayerController::PlayerChangeWeapon() void AExoPlayerController::PlayerReload() { - + ShootingComponent->Reload(); } diff --git a/Source/Exo/Public/Characters/Components/ShootingComponent.h b/Source/Exo/Public/Characters/Components/ShootingComponent.h index 6730a8d..b83de10 100644 --- a/Source/Exo/Public/Characters/Components/ShootingComponent.h +++ b/Source/Exo/Public/Characters/Components/ShootingComponent.h @@ -4,6 +4,7 @@ #include "CoreMinimal.h" #include "Components/ActorComponent.h" +#include #include "Interfaces/Damageable.h" #include "ShootingComponent.generated.h" @@ -23,9 +24,27 @@ public: UPROPERTY(EditAnywhere, Category = "Shooting") float DamageValue = 100.0f; + UPROPERTY(EditAnywhere, Category = "Shooting") + float FireRateCooldown = 1.0f; + + UPROPERTY(EditAnywhere, Category = "Shooting") + float RecoilForce = 50.0f; + + UPROPERTY(EditAnywhere, Category = "Shooting") + float ReloadTime = 3.0f; + + UPROPERTY(EditAnywhere, Category = "Ammo") + int32 CurrentAmmo = 10; + + UPROPERTY(EditAnywhere, Category = "Ammo") + int32 MaxAmmo = 10; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Debug") bool bShowDebugLine = true; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Character") + TObjectPtr PlayerCharacter; + protected: // Called when the game starts virtual void BeginPlay() override; @@ -37,6 +56,21 @@ public: UFUNCTION(Category = "Shooting") void Shoot(); - //UFUNCTION(Category = "Shooting") - //void Reload(); + UFUNCTION(Category = "Shooting") + void Reload(); + +private: + void ResetFireCooldown(); + + void ReloadCompleted(); + + FTimerHandle ShootCooldownTimer; + + FTimerHandle ReloadTimer; + + UPROPERTY(EditAnywhere, Category = "Shooting") + bool bCanShoot = true; + + UPROPERTY(EditAnywhere, Category = "Reloading") + bool bIsReloading = false; };