From 56aa855a7c013405509aa8d47de35f1910e3f477 Mon Sep 17 00:00:00 2001 From: baz Date: Thu, 4 Jan 2024 15:49:09 +0000 Subject: [PATCH 01/20] Create NakatomiCMC --- Source/Nakatomi/NakatomiCMC.cpp | 5 +++++ Source/Nakatomi/NakatomiCMC.h | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 Source/Nakatomi/NakatomiCMC.cpp create mode 100644 Source/Nakatomi/NakatomiCMC.h diff --git a/Source/Nakatomi/NakatomiCMC.cpp b/Source/Nakatomi/NakatomiCMC.cpp new file mode 100644 index 0000000..05e88d7 --- /dev/null +++ b/Source/Nakatomi/NakatomiCMC.cpp @@ -0,0 +1,5 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "NakatomiCMC.h" + diff --git a/Source/Nakatomi/NakatomiCMC.h b/Source/Nakatomi/NakatomiCMC.h new file mode 100644 index 0000000..c2d44fb --- /dev/null +++ b/Source/Nakatomi/NakatomiCMC.h @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/CharacterMovementComponent.h" +#include "NakatomiCMC.generated.h" + +/** + * + */ +UCLASS() +class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent +{ + GENERATED_BODY() + +}; -- 2.34.1 From 01aeecf953685798eac0b48eff6dd6bdf661179c Mon Sep 17 00:00:00 2001 From: baz Date: Thu, 4 Jan 2024 15:50:15 +0000 Subject: [PATCH 02/20] Replace default CharacterMovementComponent with NakatomiCMC --- Source/Nakatomi/EnemyCharacter.cpp | 2 +- Source/Nakatomi/EnemyCharacter.h | 2 +- Source/Nakatomi/NakatomiCharacter.cpp | 7 ++++++- Source/Nakatomi/NakatomiCharacter.h | 8 +++++++- Source/Nakatomi/PlayerCharacter.cpp | 2 +- Source/Nakatomi/PlayerCharacter.h | 6 +++++- 6 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Source/Nakatomi/EnemyCharacter.cpp b/Source/Nakatomi/EnemyCharacter.cpp index c7b5d01..4a90cc3 100644 --- a/Source/Nakatomi/EnemyCharacter.cpp +++ b/Source/Nakatomi/EnemyCharacter.cpp @@ -5,7 +5,7 @@ #define COLLISION_WEAPON ECC_GameTraceChannel1 -AEnemyCharacter::AEnemyCharacter() +AEnemyCharacter::AEnemyCharacter(const FObjectInitializer& ObjectInitializer) : ANakatomiCharacter(ObjectInitializer) { RandomWeaponParameters = CreateDefaultSubobject(TEXT("Random Weapon Parameters")); diff --git a/Source/Nakatomi/EnemyCharacter.h b/Source/Nakatomi/EnemyCharacter.h index 6bd79fe..4f32743 100644 --- a/Source/Nakatomi/EnemyCharacter.h +++ b/Source/Nakatomi/EnemyCharacter.h @@ -27,7 +27,7 @@ private: FTimerHandle CooldownTimerHandle; public: - AEnemyCharacter(); + AEnemyCharacter(const FObjectInitializer& ObjectInitializer); UBehaviorTree* GetBehaviourTree(); diff --git a/Source/Nakatomi/NakatomiCharacter.cpp b/Source/Nakatomi/NakatomiCharacter.cpp index 9c2afdd..c60e675 100644 --- a/Source/Nakatomi/NakatomiCharacter.cpp +++ b/Source/Nakatomi/NakatomiCharacter.cpp @@ -3,12 +3,17 @@ #include "NakatomiCharacter.h" +#include "NakatomiCMC.h" + // Sets default values -ANakatomiCharacter::ANakatomiCharacter() +ANakatomiCharacter::ANakatomiCharacter(const FObjectInitializer& ObjectInitializer) : Super( + ObjectInitializer.SetDefaultSubobjectClass(ACharacter::CharacterMovementComponentName)) { // Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; + NakatomiCMC = Cast(GetCharacterMovement()); + HealthComponent = CreateDefaultSubobject(TEXT("Health Component")); HealthComponent->OnDamaged.BindUFunction(this, "OnDamaged"); HealthComponent->OnDeath.BindUFunction(this, "OnDeath"); diff --git a/Source/Nakatomi/NakatomiCharacter.h b/Source/Nakatomi/NakatomiCharacter.h index 0c368f1..3aa1a0d 100644 --- a/Source/Nakatomi/NakatomiCharacter.h +++ b/Source/Nakatomi/NakatomiCharacter.h @@ -5,6 +5,7 @@ #include "CoreMinimal.h" #include "GameFramework/Character.h" #include "HealthComponent.h" +#include "NakatomiCMC.h" #include "Throwable.h" #include "Weapon.h" #include "NakatomiCharacter.generated.h" @@ -38,6 +39,10 @@ public: UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) TArray> ThrowableInventory; +protected: + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Meta = (AllowPrivateAccess = "true")) + UNakatomiCMC* NakatomiCMC; + private: UPROPERTY(VisibleDefaultsOnly) UHealthComponent* HealthComponent = nullptr; @@ -47,9 +52,10 @@ private: UPROPERTY(EditDefaultsOnly) int MaximumThrowableInventorySize = 4; + public: // Sets default values for this character's properties - ANakatomiCharacter(); + ANakatomiCharacter(const FObjectInitializer& ObjectInitializer); protected: // Called when the game starts or when spawned diff --git a/Source/Nakatomi/PlayerCharacter.cpp b/Source/Nakatomi/PlayerCharacter.cpp index 1ce9d3d..5e8e4fb 100644 --- a/Source/Nakatomi/PlayerCharacter.cpp +++ b/Source/Nakatomi/PlayerCharacter.cpp @@ -19,7 +19,7 @@ #define COLLISION_WEAPON ECC_GameTraceChannel1 // Sets default values -APlayerCharacter::APlayerCharacter() +APlayerCharacter::APlayerCharacter(const FObjectInitializer& ObjectInitializer) : ANakatomiCharacter(ObjectInitializer) { // Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; diff --git a/Source/Nakatomi/PlayerCharacter.h b/Source/Nakatomi/PlayerCharacter.h index 7d4323d..7507789 100644 --- a/Source/Nakatomi/PlayerCharacter.h +++ b/Source/Nakatomi/PlayerCharacter.h @@ -14,6 +14,7 @@ #include "Blueprint/UserWidget.h" #include "Perception/AIPerceptionStimuliSourceComponent.h" #include "InteractableComponent.h" +#include "NakatomiCMC.h" #include "Throwable.h" #include "PlayerCharacter.generated.h" @@ -95,6 +96,9 @@ protected: float DefaultAimSensitivity = 45.0f; private: + // UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Meta = (AllowPrivateAccess = "true")) + // UNakatomiCMC* NakatomiCMC; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true")) USpringArmComponent* CameraSpringArmComponent = nullptr; @@ -132,7 +136,7 @@ private: public: // Sets default values for this character's properties - APlayerCharacter(); + APlayerCharacter(const FObjectInitializer& ObjectInitializer); protected: // Called when the game starts or when spawned -- 2.34.1 From af8d8364a4c3063d8b456cd257caacc02f418e97 Mon Sep 17 00:00:00 2001 From: baz Date: Thu, 4 Jan 2024 15:51:03 +0000 Subject: [PATCH 03/20] Add Sprint functionality to NakatomiCMC --- Source/Nakatomi/NakatomiCMC.cpp | 117 ++++++++++++++++++++++++++++++++ Source/Nakatomi/NakatomiCMC.h | 43 ++++++++++++ 2 files changed, 160 insertions(+) diff --git a/Source/Nakatomi/NakatomiCMC.cpp b/Source/Nakatomi/NakatomiCMC.cpp index 05e88d7..7da097f 100644 --- a/Source/Nakatomi/NakatomiCMC.cpp +++ b/Source/Nakatomi/NakatomiCMC.cpp @@ -3,3 +3,120 @@ #include "NakatomiCMC.h" +#include + +// Checks if we can combine the NewMove with the current move to save on data. +// If all the data in a saved move is identical, if true, we cam tell the server to run the existing move instead. +bool UNakatomiCMC::FSavedMove_Nakatomi::CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* InCharacter, + float MaxDelta) const +{ + FSavedMove_Nakatomi* newMove = static_cast(NewMove.Get()); + + // Check if values can be combined, if not return false, if true allow super to handle combining data + if (Saved_bWantsToSprint != newMove->Saved_bWantsToSprint) + { + return false; + } + + return FSavedMove_Character::CanCombineWith(NewMove, InCharacter, MaxDelta); +} + +// Reset a save move object to empty +void UNakatomiCMC::FSavedMove_Nakatomi::Clear() +{ + FSavedMove_Character::Clear(); + + Saved_bWantsToSprint = 0; +} + +uint8 UNakatomiCMC::FSavedMove_Nakatomi::GetCompressedFlags() const +{ + uint8 Result = Super::GetCompressedFlags(); + + if (Saved_bWantsToSprint) Result = ~FLAG_Custom_0; + + return Result; +} + +void UNakatomiCMC::FSavedMove_Nakatomi::SetMoveFor(ACharacter* C, float InDeltaTime, FVector const& NewAccel, + FNetworkPredictionData_Client_Character& ClientData) +{ + FSavedMove_Character::SetMoveFor(C, InDeltaTime, NewAccel, ClientData); + + UNakatomiCMC* CharacterMovement = Cast(C->GetCharacterMovement()); + + Saved_bWantsToSprint = CharacterMovement->Safe_bWantsToSprint; +} + +void UNakatomiCMC::FSavedMove_Nakatomi::PrepMoveFor(ACharacter* C) +{ + FSavedMove_Character::PrepMoveFor(C); + + UNakatomiCMC* CharacterMovement = Cast(C->GetCharacterMovement()); + + CharacterMovement->Safe_bWantsToSprint = Saved_bWantsToSprint; +} + +UNakatomiCMC::FNetworkPredictionData_Client_Nakatomi::FNetworkPredictionData_Client_Nakatomi( + const UCharacterMovementComponent& ClientMovement) : Super(ClientMovement) +{ +} + +FSavedMovePtr UNakatomiCMC::FNetworkPredictionData_Client_Nakatomi::AllocateNewMove() +{ + return FSavedMovePtr(new FSavedMove_Nakatomi()); +} + +FNetworkPredictionData_Client* UNakatomiCMC::GetPredictionData_Client() const +{ + check(PawnOwner != nullptr) + + if (ClientPredictionData == nullptr) + { + UNakatomiCMC* MutableThis = const_cast(this); + + MutableThis->ClientPredictionData = new FNetworkPredictionData_Client_Nakatomi(*this); + MutableThis->ClientPredictionData->MaxSmoothNetUpdateDist = 92.f; + MutableThis->ClientPredictionData->NoSmoothNetUpdateDist = 140.f; + } + + return ClientPredictionData; +} + +UNakatomiCMC::UNakatomiCMC(): Safe_bWantsToSprint(false) +{ +} + +void UNakatomiCMC::UpdateFromCompressedFlags(uint8 Flags) +{ + Super::UpdateFromCompressedFlags(Flags); + + Safe_bWantsToSprint = (Flags & FSavedMove_Character::FLAG_Custom_0) != 0; +} + +void UNakatomiCMC::OnMovementUpdated(float DeltaSeconds, const FVector& OldLocation, const FVector& OldVelocity) +{ + Super::OnMovementUpdated(DeltaSeconds, OldLocation, OldVelocity); + + if (MovementMode == MOVE_Walking) + { + if (Safe_bWantsToSprint) + { + MaxWalkSpeed = Sprint_MaxWalkSpeed; + } + else + { + MaxWalkSpeed = Walk_MaxWalkSpeed; + } + } +} + +void UNakatomiCMC::EnableSprint() +{ + Safe_bWantsToSprint = true; +} + +void UNakatomiCMC::DisableSprint() +{ + Safe_bWantsToSprint = false; +} \ No newline at end of file diff --git a/Source/Nakatomi/NakatomiCMC.h b/Source/Nakatomi/NakatomiCMC.h index c2d44fb..16f41cd 100644 --- a/Source/Nakatomi/NakatomiCMC.h +++ b/Source/Nakatomi/NakatomiCMC.h @@ -13,5 +13,48 @@ UCLASS() class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent { GENERATED_BODY() + + class FSavedMove_Nakatomi : public FSavedMove_Character + { + typedef FSavedMove_Character Super; + + uint8 Saved_bWantsToSprint:1; + + virtual bool CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* InCharacter, float MaxDelta) const override; + virtual void Clear() override; + virtual uint8 GetCompressedFlags() const override; + virtual void SetMoveFor(ACharacter* C, float InDeltaTime, FVector const& NewAccel, FNetworkPredictionData_Client_Character& ClientData) override; + virtual void PrepMoveFor(ACharacter* C) override; + }; + + class FNetworkPredictionData_Client_Nakatomi : public FNetworkPredictionData_Client_Character + { + public: + FNetworkPredictionData_Client_Nakatomi(const UCharacterMovementComponent& ClientMovement); + + typedef FNetworkPredictionData_Client_Character Super; + + virtual FSavedMovePtr AllocateNewMove() override; + }; + + UPROPERTY(EditDefaultsOnly) float Sprint_MaxWalkSpeed; + UPROPERTY(EditDefaultsOnly) float Walk_MaxWalkSpeed; + bool Safe_bWantsToSprint; + +public: + UNakatomiCMC(); + + FNetworkPredictionData_Client* GetPredictionData_Client() const override; +protected: + virtual void UpdateFromCompressedFlags(uint8 Flags) override; + + virtual void OnMovementUpdated(float DeltaSeconds, const FVector& OldLocation, const FVector& OldVelocity) override; + +public: + UFUNCTION(BlueprintCallable) + void EnableSprint(); + + UFUNCTION(BlueprintCallable) + void DisableSprint(); }; -- 2.34.1 From ab3f624ade7fe7e0072f0f35854fc4eca89d87f6 Mon Sep 17 00:00:00 2001 From: baz Date: Thu, 4 Jan 2024 15:53:24 +0000 Subject: [PATCH 04/20] Use NakatomiCMC to set Walk and Sprint speed I am temporarily breaking ADS movement, this will be fixed in subsequent commits --- Source/Nakatomi/PlayerCharacter.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Source/Nakatomi/PlayerCharacter.cpp b/Source/Nakatomi/PlayerCharacter.cpp index 5e8e4fb..ba09290 100644 --- a/Source/Nakatomi/PlayerCharacter.cpp +++ b/Source/Nakatomi/PlayerCharacter.cpp @@ -25,7 +25,7 @@ APlayerCharacter::APlayerCharacter(const FObjectInitializer& ObjectInitializer) PrimaryActorTick.bCanEverTick = true; PrimaryActorTick.SetTickFunctionEnable(true); PrimaryActorTick.bStartWithTickEnabled = true; - + //bUseControllerRotationPitch = true; //bUseControllerRotationYaw = true; //bUseControllerRotationRoll = false; @@ -56,9 +56,8 @@ APlayerCharacter::APlayerCharacter(const FObjectInitializer& ObjectInitializer) CameraADSSpringArmComponent->SocketOffset = {0.0f, 50.0f, 75.0f}; // Setup the character movement - UCharacterMovementComponent* CharacterMovementComponent = GetCharacterMovement(); - CharacterMovementComponent->AirControl = 1.0f; - CharacterMovementComponent->bOrientRotationToMovement = true; + GetCharacterMovement()->AirControl = 1.0f; + GetCharacterMovement()->bOrientRotationToMovement = true; // Setup the character perception component PerceptionSource = CreateDefaultSubobject(TEXT("Perception Source Stimuli")); @@ -269,16 +268,18 @@ void APlayerCharacter::QuitCallback(const FInputActionInstance& Instance) void APlayerCharacter::SetSprintingCallback(const FInputActionInstance& Instance) { - IsSpriting = true; - - SetMovementSpeed(); + if (NakatomiCMC) + { + NakatomiCMC->EnableSprint(); + } } void APlayerCharacter::SetWalkingCallback(const FInputActionInstance& Instance) { - IsSpriting = false; - - SetMovementSpeed(); + if (NakatomiCMC) + { + NakatomiCMC->DisableSprint(); + } } void APlayerCharacter::CalculateHits(TArray* hits) @@ -450,7 +451,7 @@ void APlayerCharacter::OnDeath() void APlayerCharacter::SetMovementSpeed() { - if (IsADS) + /*if (IsADS) { GetCharacterMovement()->MaxWalkSpeed = DefaultMovementSpeed * ADSSpeedMultiplier; } @@ -461,7 +462,7 @@ void APlayerCharacter::SetMovementSpeed() else { GetCharacterMovement()->MaxWalkSpeed = DefaultMovementSpeed; - } + }*/ } void APlayerCharacter::WeaponSwitchingCallback(const FInputActionInstance& Instance) -- 2.34.1 From 6bccd097bbc7ed7c165931548a7d7f43015b55ca Mon Sep 17 00:00:00 2001 From: baz Date: Thu, 4 Jan 2024 15:53:50 +0000 Subject: [PATCH 05/20] Set new Walk and Sprint speed defaults --- Content/Player/PlayerCharacter.uasset | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Content/Player/PlayerCharacter.uasset b/Content/Player/PlayerCharacter.uasset index 37f45d6..fe17cd9 100644 --- a/Content/Player/PlayerCharacter.uasset +++ b/Content/Player/PlayerCharacter.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d6df619c920a959f560e32aaaf4195ea7caa5098bbd6a131b48a850e5ce0b3b9 -size 39130 +oid sha256:8c9d65191b61251cd739587da98106bc5ef01e954c737743f8dc5dfc3203ff8e +size 40997 -- 2.34.1 From 08fbe9dbe13996c269f315cc07f6c91eccead406 Mon Sep 17 00:00:00 2001 From: baz Date: Thu, 4 Jan 2024 20:31:33 +0000 Subject: [PATCH 06/20] Assign NakatomiCMC in BeginPlay and add getter --- Source/Nakatomi/NakatomiCharacter.cpp | 7 +++++++ Source/Nakatomi/NakatomiCharacter.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/Source/Nakatomi/NakatomiCharacter.cpp b/Source/Nakatomi/NakatomiCharacter.cpp index c60e675..4f1e224 100644 --- a/Source/Nakatomi/NakatomiCharacter.cpp +++ b/Source/Nakatomi/NakatomiCharacter.cpp @@ -25,6 +25,8 @@ void ANakatomiCharacter::BeginPlay() Super::BeginPlay(); SetInventoryToDefault(); + + NakatomiCMC = Cast(GetCharacterMovement()); } // Called every frame @@ -237,6 +239,11 @@ void ANakatomiCharacter::PushThrowableToInventory(TSubclassOf Throwa } } +UNakatomiCMC* ANakatomiCharacter::GetCharacterMovementComponent() +{ + return NakatomiCMC; +} + void ANakatomiCharacter::CalculateHits(TArray* hits) { } diff --git a/Source/Nakatomi/NakatomiCharacter.h b/Source/Nakatomi/NakatomiCharacter.h index 3aa1a0d..1951dc3 100644 --- a/Source/Nakatomi/NakatomiCharacter.h +++ b/Source/Nakatomi/NakatomiCharacter.h @@ -104,6 +104,8 @@ public: void PushThrowableToInventory(TSubclassOf Throwable); + UNakatomiCMC* GetCharacterMovementComponent(); + protected: virtual void CalculateHits(TArray* hits); -- 2.34.1 From 283b53624240e573040ab842ece2e92a75373d00 Mon Sep 17 00:00:00 2001 From: baz Date: Thu, 4 Jan 2024 20:31:44 +0000 Subject: [PATCH 07/20] Add Crouch functionality --- Source/Nakatomi/NakatomiCMC.cpp | 21 +++++++++++---- Source/Nakatomi/NakatomiCMC.h | 6 +++++ Source/Nakatomi/PlayerCharacter.cpp | 40 +++++++++++++++++++++++++---- Source/Nakatomi/PlayerCharacter.h | 7 +++++ 4 files changed, 64 insertions(+), 10 deletions(-) diff --git a/Source/Nakatomi/NakatomiCMC.cpp b/Source/Nakatomi/NakatomiCMC.cpp index 7da097f..ab8e374 100644 --- a/Source/Nakatomi/NakatomiCMC.cpp +++ b/Source/Nakatomi/NakatomiCMC.cpp @@ -5,6 +5,11 @@ #include +UNakatomiCMC::UNakatomiCMC(): Safe_bWantsToSprint(false) +{ + NavAgentProps.bCanCrouch = true; +} + // Checks if we can combine the NewMove with the current move to save on data. // If all the data in a saved move is identical, if true, we cam tell the server to run the existing move instead. bool UNakatomiCMC::FSavedMove_Nakatomi::CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* InCharacter, @@ -83,10 +88,6 @@ FNetworkPredictionData_Client* UNakatomiCMC::GetPredictionData_Client() const return ClientPredictionData; } -UNakatomiCMC::UNakatomiCMC(): Safe_bWantsToSprint(false) -{ -} - void UNakatomiCMC::UpdateFromCompressedFlags(uint8 Flags) { Super::UpdateFromCompressedFlags(Flags); @@ -119,4 +120,14 @@ void UNakatomiCMC::EnableSprint() void UNakatomiCMC::DisableSprint() { Safe_bWantsToSprint = false; -} \ No newline at end of file +} + +void UNakatomiCMC::EnableCrouch() +{ + bWantsToCrouch = true; +} + +void UNakatomiCMC::DisableCrouch() +{ + bWantsToCrouch = false; +} diff --git a/Source/Nakatomi/NakatomiCMC.h b/Source/Nakatomi/NakatomiCMC.h index 16f41cd..689975e 100644 --- a/Source/Nakatomi/NakatomiCMC.h +++ b/Source/Nakatomi/NakatomiCMC.h @@ -57,4 +57,10 @@ public: UFUNCTION(BlueprintCallable) void DisableSprint(); + + UFUNCTION(BlueprintCallable) + void EnableCrouch(); + + UFUNCTION(BlueprintCallable) + void DisableCrouch(); }; diff --git a/Source/Nakatomi/PlayerCharacter.cpp b/Source/Nakatomi/PlayerCharacter.cpp index ba09290..e17a04f 100644 --- a/Source/Nakatomi/PlayerCharacter.cpp +++ b/Source/Nakatomi/PlayerCharacter.cpp @@ -187,6 +187,12 @@ void APlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputCom { Input->BindAction(PauseAction, ETriggerEvent::Completed, this, &APlayerCharacter::PauseCallback); } + + if (CrouchAction) + { + Input->BindAction(CrouchAction, ETriggerEvent::Started, this, &APlayerCharacter::BeginCrouchCallback); + Input->BindAction(CrouchAction, ETriggerEvent::Completed, this, &APlayerCharacter::EndCrouchCallback); + } } } @@ -268,17 +274,21 @@ void APlayerCharacter::QuitCallback(const FInputActionInstance& Instance) void APlayerCharacter::SetSprintingCallback(const FInputActionInstance& Instance) { - if (NakatomiCMC) + UNakatomiCMC* cmc = GetCharacterMovementComponent(); + + if (cmc) { - NakatomiCMC->EnableSprint(); + cmc->EnableSprint(); } } void APlayerCharacter::SetWalkingCallback(const FInputActionInstance& Instance) { - if (NakatomiCMC) + UNakatomiCMC* cmc = GetCharacterMovementComponent(); + + if (cmc) { - NakatomiCMC->DisableSprint(); + cmc->DisableSprint(); } } @@ -536,6 +546,26 @@ void APlayerCharacter::PauseCallback(const FInputActionInstance& Instance) } } +void APlayerCharacter::BeginCrouchCallback(const FInputActionInstance& Instance) +{ + UNakatomiCMC* cmc = GetCharacterMovementComponent(); + + if (cmc) + { + cmc->EnableCrouch(); + } +} + +void APlayerCharacter::EndCrouchCallback(const FInputActionInstance& Instance) +{ + UNakatomiCMC* cmc = GetCharacterMovementComponent(); + + if (cmc) + { + cmc->DisableCrouch(); + } +} + void APlayerCharacter::OnFire() { if (!IsFiring || CurrentWeapon->GetAmmoCount() == 0) @@ -684,4 +714,4 @@ AThrowable* APlayerCharacter::ThrowThrowable() } return nullptr; -} +} \ No newline at end of file diff --git a/Source/Nakatomi/PlayerCharacter.h b/Source/Nakatomi/PlayerCharacter.h index 7507789..5f75c86 100644 --- a/Source/Nakatomi/PlayerCharacter.h +++ b/Source/Nakatomi/PlayerCharacter.h @@ -64,6 +64,9 @@ public: UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) UInputAction* AimDownSightsAction; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) + UInputAction* CrouchAction; UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) TSoftObjectPtr InputMappingContext; @@ -174,6 +177,10 @@ public: void EndAimDownSightsCallback(const FInputActionInstance& Instance); void PauseCallback(const FInputActionInstance& Instance); + + void BeginCrouchCallback(const FInputActionInstance& Instance); + + void EndCrouchCallback(const FInputActionInstance& Instance); virtual void OnFire() override; -- 2.34.1 From 58f779c887b5a3366e04fa880b3fb3dcde71fde8 Mon Sep 17 00:00:00 2001 From: baz Date: Thu, 4 Jan 2024 20:32:05 +0000 Subject: [PATCH 08/20] Create Crouch input action and assign it to the InputMappingContext --- Content/Input/Actions/IA_Crouch.uasset | 3 +++ Content/Input/InputMappingContext.uasset | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 Content/Input/Actions/IA_Crouch.uasset diff --git a/Content/Input/Actions/IA_Crouch.uasset b/Content/Input/Actions/IA_Crouch.uasset new file mode 100644 index 0000000..9439682 --- /dev/null +++ b/Content/Input/Actions/IA_Crouch.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:419dec41cba9ec94f064280d7d2312e3a9f99bc278ab5cb0931e2e0e58f47850 +size 1340 diff --git a/Content/Input/InputMappingContext.uasset b/Content/Input/InputMappingContext.uasset index 318dff2..97ca042 100644 --- a/Content/Input/InputMappingContext.uasset +++ b/Content/Input/InputMappingContext.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b2c749222f80e3692e3deeea1e560981de77784e270c77eac4049875b0f33774 -size 19556 +oid sha256:de1d417c9d38a0a6340834b2e26be834ebb75b539bd8d6e3072f20b798a48a90 +size 20933 -- 2.34.1 From fc7095fd756068d96cbaf249d353875a6187863a Mon Sep 17 00:00:00 2001 From: baz Date: Thu, 4 Jan 2024 20:32:21 +0000 Subject: [PATCH 09/20] Add Crouch input to PlayerCharacter blueprint --- Content/Player/PlayerCharacter.uasset | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Content/Player/PlayerCharacter.uasset b/Content/Player/PlayerCharacter.uasset index fe17cd9..081877a 100644 --- a/Content/Player/PlayerCharacter.uasset +++ b/Content/Player/PlayerCharacter.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8c9d65191b61251cd739587da98106bc5ef01e954c737743f8dc5dfc3203ff8e -size 40997 +oid sha256:744bb92f90935559c0e4c0f3f62f34cf45dddb5232be266360bcd1fbeefbe250 +size 41175 -- 2.34.1 From 2cdb97b7abe992d5c29c0d028592d17caab1d22b Mon Sep 17 00:00:00 2001 From: baz Date: Thu, 11 Jan 2024 19:20:41 +0000 Subject: [PATCH 10/20] Add NakatomiCharacter and NakatomiCMC to Nakatomi.h --- Source/Nakatomi/Nakatomi.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Nakatomi/Nakatomi.h b/Source/Nakatomi/Nakatomi.h index ddbf2e2..038523c 100644 --- a/Source/Nakatomi/Nakatomi.h +++ b/Source/Nakatomi/Nakatomi.h @@ -3,3 +3,6 @@ #pragma once #include "CoreMinimal.h" + +class ANakatomiCharacter; +class UNakatomiCMC; \ No newline at end of file -- 2.34.1 From 293358737c53e0ce76eca94a49a993f2e4d2f299 Mon Sep 17 00:00:00 2001 From: baz Date: Thu, 11 Jan 2024 19:21:15 +0000 Subject: [PATCH 11/20] Add initial custom slide movement implementation --- Source/Nakatomi/NakatomiCMC.cpp | 154 ++++++++++++++++++++++++++++ Source/Nakatomi/NakatomiCMC.h | 59 ++++++++++- Source/Nakatomi/NakatomiCharacter.h | 2 +- 3 files changed, 212 insertions(+), 3 deletions(-) diff --git a/Source/Nakatomi/NakatomiCMC.cpp b/Source/Nakatomi/NakatomiCMC.cpp index ab8e374..93e92d8 100644 --- a/Source/Nakatomi/NakatomiCMC.cpp +++ b/Source/Nakatomi/NakatomiCMC.cpp @@ -3,13 +3,22 @@ #include "NakatomiCMC.h" +#include #include +#include "NakatomiCharacter.h" UNakatomiCMC::UNakatomiCMC(): Safe_bWantsToSprint(false) { NavAgentProps.bCanCrouch = true; } +void UNakatomiCMC::InitializeComponent() +{ + Super::InitializeComponent(); + + NakatomiCharacterOwner = Cast(GetOwner()); +} + // Checks if we can combine the NewMove with the current move to save on data. // If all the data in a saved move is identical, if true, we cam tell the server to run the existing move instead. bool UNakatomiCMC::FSavedMove_Nakatomi::CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* InCharacter, @@ -51,6 +60,7 @@ void UNakatomiCMC::FSavedMove_Nakatomi::SetMoveFor(ACharacter* C, float InDeltaT UNakatomiCMC* CharacterMovement = Cast(C->GetCharacterMovement()); Saved_bWantsToSprint = CharacterMovement->Safe_bWantsToSprint; + Saved_bPrevWantsToCrouch = CharacterMovement->Safe_bPrevWantsToCrouch; } void UNakatomiCMC::FSavedMove_Nakatomi::PrepMoveFor(ACharacter* C) @@ -60,6 +70,7 @@ void UNakatomiCMC::FSavedMove_Nakatomi::PrepMoveFor(ACharacter* C) UNakatomiCMC* CharacterMovement = Cast(C->GetCharacterMovement()); CharacterMovement->Safe_bWantsToSprint = Saved_bWantsToSprint; + CharacterMovement->Safe_bPrevWantsToCrouch = Saved_bPrevWantsToCrouch; } UNakatomiCMC::FNetworkPredictionData_Client_Nakatomi::FNetworkPredictionData_Client_Nakatomi( @@ -110,6 +121,51 @@ void UNakatomiCMC::OnMovementUpdated(float DeltaSeconds, const FVector& OldLocat MaxWalkSpeed = Walk_MaxWalkSpeed; } } + + Safe_bPrevWantsToCrouch = bWantsToCrouch; +} + +bool UNakatomiCMC::IsMovingOnGround() const +{ + return Super::IsMovingOnGround() || IsCustomMovementMode(CMOVE_Slide); +} + +bool UNakatomiCMC::CanCrouchInCurrentState() const +{ + return Super::CanCrouchInCurrentState() && IsMovingOnGround(); +} + +void UNakatomiCMC::UpdateCharacterStateBeforeMovement(float DeltaSeconds) +{ + if (MovementMode == MOVE_Walking && !bWantsToCrouch && Safe_bPrevWantsToCrouch) + { + FHitResult PotentialSlideSurface; + if (Velocity.SizeSquared() > pow(Slide_MinSpeed, 2) && GetSlideSurface(PotentialSlideSurface)) + { + EnterSlide(); + } + } + + if (IsCustomMovementMode(CMOVE_Slide) && !bWantsToCrouch) + { + ExitSlide(); + } + + Super::UpdateCharacterStateBeforeMovement(DeltaSeconds); +} + +void UNakatomiCMC::PhysCustom(float deltaTime, int32 Iterations) +{ + Super::PhysCustom(deltaTime, Iterations); + + switch (CustomMovementMode) + { + case CMOVE_Slide: + PhysSlide(deltaTime, Iterations); + break; + default: + UE_LOG(LogTemp, Fatal, TEXT("Invalid Movement Mode")); + } } void UNakatomiCMC::EnableSprint() @@ -131,3 +187,101 @@ void UNakatomiCMC::DisableCrouch() { bWantsToCrouch = false; } + +bool UNakatomiCMC::IsCustomMovementMode(ECustomMovementMove InCustomMovementMode) const +{ + return MovementMode == MOVE_Custom && CustomMovementMode == InCustomMovementMode; +} + +void UNakatomiCMC::EnterSlide() +{ + bWantsToCrouch = true; + Velocity += Velocity.GetSafeNormal2D() * Slide_EnterImpulse; + SetMovementMode(MOVE_Custom, CMOVE_Slide); +} + +void UNakatomiCMC::ExitSlide() +{ + bWantsToCrouch = false; + + FQuat NewRotation = FRotationMatrix::MakeFromXZ(UpdatedComponent->GetForwardVector().GetSafeNormal2D(), FVector::UpVector).ToQuat(); + FHitResult Hit; + SafeMoveUpdatedComponent(FVector::ZeroVector, NewRotation, true, Hit); + SetMovementMode(MOVE_Walking); +} + +void UNakatomiCMC::PhysSlide(float deltaTime, int32 Iterations) +{ + if (deltaTime < MIN_TICK_TIME) return; + + // This is probably not needed for Sliding but including for completeness, will likely remove later. + RestorePreAdditiveRootMotionVelocity(); + + FHitResult SurfaceHit; + if (!GetSlideSurface(SurfaceHit) || Velocity.SizeSquared() < pow(Slide_MinSpeed, 2)) + { + ExitSlide(); + StartNewPhysics(deltaTime, Iterations); + } + + // Surface Gravity + Velocity += Slide_GravityForce * FVector::DownVector * deltaTime; + + // Calculate Strafe + if (FMath::Abs(FVector::DotProduct(Acceleration.GetSafeNormal(), UpdatedComponent->GetRightVector())) > 0.5f) + { + Acceleration = Acceleration.ProjectOnTo(UpdatedComponent->GetRightVector()); + } + else + { + Acceleration = FVector::ZeroVector; + } + + // Calculate Velocity + if (!HasAnimRootMotion() && !CurrentRootMotion.HasOverrideVelocity()) + { + CalcVelocity(deltaTime, Slide_Friction, true, GetMaxBrakingDeceleration()); + } + ApplyRootMotionToVelocity(deltaTime); + + // Perform Move + Iterations++; + bJustTeleported = false; + + FVector OldLocation = UpdatedComponent->GetComponentLocation(); + FQuat OldRotation = UpdatedComponent->GetComponentRotation().Quaternion(); + + FHitResult Hit(1.f); + FVector AdjustedVelocity = Velocity * deltaTime; + FVector VelocityPlaneDirection = FVector::VectorPlaneProject(Velocity, SurfaceHit.Normal).GetSafeNormal(); + FQuat NewRotation = FRotationMatrix::MakeFromXZ(VelocityPlaneDirection, SurfaceHit.Normal).ToQuat(); + SafeMoveUpdatedComponent(AdjustedVelocity, NewRotation, true, Hit); + + // Post Move Checks + if (Hit.Time < 1.f) + { + HandleImpact(Hit, deltaTime, AdjustedVelocity); + SlideAlongSurface(AdjustedVelocity, (1.f - Hit.Time), Hit.Normal, Hit, true); + } + + FHitResult NewSurfaceHit; + if (!GetSlideSurface(NewSurfaceHit) || Velocity.SizeSquared() < pow(Slide_MinSpeed, 2)) + { + ExitSlide(); + } + + // Update outgoing Velocity and Acceleration + if (!bJustTeleported && !HasAnimRootMotion() && !CurrentRootMotion.HasOverrideVelocity()) + { + Velocity = (UpdatedComponent->GetComponentLocation() - OldLocation) / deltaTime; + } +} + +bool UNakatomiCMC::GetSlideSurface(FHitResult& Hit) const +{ + const FVector Start = UpdatedComponent->GetComponentLocation(); + const FVector End = Start + CharacterOwner->GetCapsuleComponent()->GetScaledCapsuleHalfHeight() * 2.f * FVector::DownVector; + const FName ProfileName = TEXT("BlockAll"); + + return GetWorld()->LineTraceSingleByProfile(Hit, Start, End, ProfileName); +} diff --git a/Source/Nakatomi/NakatomiCMC.h b/Source/Nakatomi/NakatomiCMC.h index 689975e..49ac9a9 100644 --- a/Source/Nakatomi/NakatomiCMC.h +++ b/Source/Nakatomi/NakatomiCMC.h @@ -3,9 +3,18 @@ #pragma once #include "CoreMinimal.h" +#include "Nakatomi.h" #include "GameFramework/CharacterMovementComponent.h" #include "NakatomiCMC.generated.h" +UENUM(BlueprintType) +enum ECustomMovementMove +{ + CMOVE_None UMETA(Hidden), + CMOVE_Slide UMETA(DisplayName = "Slide"), + CMOVE_MAX UMETA(Hidden), +}; + /** * */ @@ -18,8 +27,11 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent { typedef FSavedMove_Character Super; + // Flag uint8 Saved_bWantsToSprint:1; + uint8 Saved_bPrevWantsToCrouch:1; + virtual bool CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* InCharacter, float MaxDelta) const override; virtual void Clear() override; virtual uint8 GetCompressedFlags() const override; @@ -37,19 +49,49 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent virtual FSavedMovePtr AllocateNewMove() override; }; - UPROPERTY(EditDefaultsOnly) float Sprint_MaxWalkSpeed; - UPROPERTY(EditDefaultsOnly) float Walk_MaxWalkSpeed; + UPROPERTY(EditDefaultsOnly) + float Sprint_MaxWalkSpeed; + + UPROPERTY(EditDefaultsOnly) + float Walk_MaxWalkSpeed; + + UPROPERTY(EditDefaultsOnly) + float Slide_MinSpeed = 10.f; + + UPROPERTY(EditDefaultsOnly) + float Slide_EnterImpulse = 2000.f; + + UPROPERTY(EditDefaultsOnly) + float Slide_GravityForce = 5000.f; + + UPROPERTY(EditDefaultsOnly) + float Slide_Friction = 1.3f; bool Safe_bWantsToSprint; + bool Safe_bPrevWantsToCrouch; + + UPROPERTY(Transient) + ANakatomiCharacter* NakatomiCharacterOwner; public: UNakatomiCMC(); +protected: + void InitializeComponent() override; + FNetworkPredictionData_Client* GetPredictionData_Client() const override; protected: virtual void UpdateFromCompressedFlags(uint8 Flags) override; virtual void OnMovementUpdated(float DeltaSeconds, const FVector& OldLocation, const FVector& OldVelocity) override; + + virtual bool IsMovingOnGround() const override; + + virtual bool CanCrouchInCurrentState() const override; + + virtual void UpdateCharacterStateBeforeMovement(float DeltaSeconds) override; + + virtual void PhysCustom(float deltaTime, int32 Iterations) override; public: UFUNCTION(BlueprintCallable) @@ -63,4 +105,17 @@ public: UFUNCTION(BlueprintCallable) void DisableCrouch(); + + UFUNCTION() + bool IsCustomMovementMode(ECustomMovementMove InCustomMovementMode) const; + +private: + + void EnterSlide(); + + void ExitSlide(); + + void PhysSlide(float deltaTime, int32 Iterations); // Every movement mode requires a physics function to work + + bool GetSlideSurface(FHitResult& Hit) const; }; diff --git a/Source/Nakatomi/NakatomiCharacter.h b/Source/Nakatomi/NakatomiCharacter.h index 1951dc3..574f69d 100644 --- a/Source/Nakatomi/NakatomiCharacter.h +++ b/Source/Nakatomi/NakatomiCharacter.h @@ -5,7 +5,7 @@ #include "CoreMinimal.h" #include "GameFramework/Character.h" #include "HealthComponent.h" -#include "NakatomiCMC.h" +#include "Nakatomi.h" #include "Throwable.h" #include "Weapon.h" #include "NakatomiCharacter.generated.h" -- 2.34.1 From bf45b09cd7ca2bcab9c20519a3073b0ee5cee3b9 Mon Sep 17 00:00:00 2001 From: baz Date: Fri, 12 Jan 2024 15:30:55 +0000 Subject: [PATCH 12/20] Add Slide Input Action --- Content/Input/Actions/IA_Slide.uasset | 3 +++ Content/Input/InputMappingContext.uasset | 4 ++-- Content/Player/PlayerCharacter.uasset | 4 ++-- Source/Nakatomi/NakatomiCMC.cpp | 10 +++++++++ Source/Nakatomi/NakatomiCMC.h | 6 ++++++ Source/Nakatomi/PlayerCharacter.cpp | 26 ++++++++++++++++++++++++ Source/Nakatomi/PlayerCharacter.h | 7 +++++++ 7 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 Content/Input/Actions/IA_Slide.uasset diff --git a/Content/Input/Actions/IA_Slide.uasset b/Content/Input/Actions/IA_Slide.uasset new file mode 100644 index 0000000..952b084 --- /dev/null +++ b/Content/Input/Actions/IA_Slide.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:994df7bb660cf49d7f7dce90b19640070e8017a9b01d4f4889577c6ca55fb304 +size 1335 diff --git a/Content/Input/InputMappingContext.uasset b/Content/Input/InputMappingContext.uasset index 97ca042..4c35457 100644 --- a/Content/Input/InputMappingContext.uasset +++ b/Content/Input/InputMappingContext.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de1d417c9d38a0a6340834b2e26be834ebb75b539bd8d6e3072f20b798a48a90 -size 20933 +oid sha256:a3a7a8439ad88551e785e4c83a04d9753526bf6fb24d900abd1b3a513b2df181 +size 21067 diff --git a/Content/Player/PlayerCharacter.uasset b/Content/Player/PlayerCharacter.uasset index 081877a..5e9b6ea 100644 --- a/Content/Player/PlayerCharacter.uasset +++ b/Content/Player/PlayerCharacter.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:744bb92f90935559c0e4c0f3f62f34cf45dddb5232be266360bcd1fbeefbe250 -size 41175 +oid sha256:587f042237e7a5d1f718068f17e6d94f9dd6133fadbd5bb3f8a4d652a1781adc +size 41366 diff --git a/Source/Nakatomi/NakatomiCMC.cpp b/Source/Nakatomi/NakatomiCMC.cpp index 93e92d8..efea661 100644 --- a/Source/Nakatomi/NakatomiCMC.cpp +++ b/Source/Nakatomi/NakatomiCMC.cpp @@ -188,6 +188,16 @@ void UNakatomiCMC::DisableCrouch() bWantsToCrouch = false; } +void UNakatomiCMC::EnableSlide() +{ + EnterSlide(); +} + +void UNakatomiCMC::DisableSlide() +{ + ExitSlide(); +} + bool UNakatomiCMC::IsCustomMovementMode(ECustomMovementMove InCustomMovementMode) const { return MovementMode == MOVE_Custom && CustomMovementMode == InCustomMovementMode; diff --git a/Source/Nakatomi/NakatomiCMC.h b/Source/Nakatomi/NakatomiCMC.h index 49ac9a9..8ae8ceb 100644 --- a/Source/Nakatomi/NakatomiCMC.h +++ b/Source/Nakatomi/NakatomiCMC.h @@ -106,6 +106,12 @@ public: UFUNCTION(BlueprintCallable) void DisableCrouch(); + UFUNCTION(BlueprintCallable) + void EnableSlide(); + + UFUNCTION(BlueprintCallable) + void DisableSlide(); + UFUNCTION() bool IsCustomMovementMode(ECustomMovementMove InCustomMovementMode) const; diff --git a/Source/Nakatomi/PlayerCharacter.cpp b/Source/Nakatomi/PlayerCharacter.cpp index e17a04f..a79acd6 100644 --- a/Source/Nakatomi/PlayerCharacter.cpp +++ b/Source/Nakatomi/PlayerCharacter.cpp @@ -193,6 +193,12 @@ void APlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputCom Input->BindAction(CrouchAction, ETriggerEvent::Started, this, &APlayerCharacter::BeginCrouchCallback); Input->BindAction(CrouchAction, ETriggerEvent::Completed, this, &APlayerCharacter::EndCrouchCallback); } + + if (SlideAction) + { + Input->BindAction(SlideAction, ETriggerEvent::Started, this, &APlayerCharacter::BeginSlideCallback); + Input->BindAction(SlideAction, ETriggerEvent::Completed, this, &APlayerCharacter::EndSlideCallback); + } } } @@ -566,6 +572,26 @@ void APlayerCharacter::EndCrouchCallback(const FInputActionInstance& Instance) } } +void APlayerCharacter::BeginSlideCallback(const FInputActionInstance& Instance) +{ + UNakatomiCMC* cmc = GetCharacterMovementComponent(); + + if (cmc) + { + cmc->EnableSlide(); + } +} + +void APlayerCharacter::EndSlideCallback(const FInputActionInstance& Instance) +{ + UNakatomiCMC* cmc = GetCharacterMovementComponent(); + + if (cmc) + { + cmc->DisableSlide(); + } +} + void APlayerCharacter::OnFire() { if (!IsFiring || CurrentWeapon->GetAmmoCount() == 0) diff --git a/Source/Nakatomi/PlayerCharacter.h b/Source/Nakatomi/PlayerCharacter.h index 5f75c86..d042695 100644 --- a/Source/Nakatomi/PlayerCharacter.h +++ b/Source/Nakatomi/PlayerCharacter.h @@ -67,6 +67,9 @@ public: UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) UInputAction* CrouchAction; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) + UInputAction* SlideAction; UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) TSoftObjectPtr InputMappingContext; @@ -181,6 +184,10 @@ public: void BeginCrouchCallback(const FInputActionInstance& Instance); void EndCrouchCallback(const FInputActionInstance& Instance); + + void BeginSlideCallback(const FInputActionInstance& Instance); + + void EndSlideCallback(const FInputActionInstance& Instance); virtual void OnFire() override; -- 2.34.1 From 9bb322554263172bc854eb2081a90594bed28f4b Mon Sep 17 00:00:00 2001 From: baz Date: Fri, 12 Jan 2024 15:53:23 +0000 Subject: [PATCH 13/20] Change Slide to work with Slide Input Action --- Source/Nakatomi/NakatomiCMC.cpp | 18 ++++++++---------- Source/Nakatomi/NakatomiCMC.h | 12 ++++++------ 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/Source/Nakatomi/NakatomiCMC.cpp b/Source/Nakatomi/NakatomiCMC.cpp index efea661..4cb16ac 100644 --- a/Source/Nakatomi/NakatomiCMC.cpp +++ b/Source/Nakatomi/NakatomiCMC.cpp @@ -60,7 +60,7 @@ void UNakatomiCMC::FSavedMove_Nakatomi::SetMoveFor(ACharacter* C, float InDeltaT UNakatomiCMC* CharacterMovement = Cast(C->GetCharacterMovement()); Saved_bWantsToSprint = CharacterMovement->Safe_bWantsToSprint; - Saved_bPrevWantsToCrouch = CharacterMovement->Safe_bPrevWantsToCrouch; + Saved_bWantsToSlide = CharacterMovement->Safe_bWantsToSlide; } void UNakatomiCMC::FSavedMove_Nakatomi::PrepMoveFor(ACharacter* C) @@ -70,7 +70,7 @@ void UNakatomiCMC::FSavedMove_Nakatomi::PrepMoveFor(ACharacter* C) UNakatomiCMC* CharacterMovement = Cast(C->GetCharacterMovement()); CharacterMovement->Safe_bWantsToSprint = Saved_bWantsToSprint; - CharacterMovement->Safe_bPrevWantsToCrouch = Saved_bPrevWantsToCrouch; + CharacterMovement->Safe_bWantsToSlide = Saved_bWantsToSlide; } UNakatomiCMC::FNetworkPredictionData_Client_Nakatomi::FNetworkPredictionData_Client_Nakatomi( @@ -121,8 +121,6 @@ void UNakatomiCMC::OnMovementUpdated(float DeltaSeconds, const FVector& OldLocat MaxWalkSpeed = Walk_MaxWalkSpeed; } } - - Safe_bPrevWantsToCrouch = bWantsToCrouch; } bool UNakatomiCMC::IsMovingOnGround() const @@ -137,7 +135,7 @@ bool UNakatomiCMC::CanCrouchInCurrentState() const void UNakatomiCMC::UpdateCharacterStateBeforeMovement(float DeltaSeconds) { - if (MovementMode == MOVE_Walking && !bWantsToCrouch && Safe_bPrevWantsToCrouch) + if (MovementMode == MOVE_Walking && Safe_bWantsToSlide) { FHitResult PotentialSlideSurface; if (Velocity.SizeSquared() > pow(Slide_MinSpeed, 2) && GetSlideSurface(PotentialSlideSurface)) @@ -146,7 +144,7 @@ void UNakatomiCMC::UpdateCharacterStateBeforeMovement(float DeltaSeconds) } } - if (IsCustomMovementMode(CMOVE_Slide) && !bWantsToCrouch) + if (IsCustomMovementMode(CMOVE_Slide) && !Safe_bWantsToSlide) { ExitSlide(); } @@ -190,12 +188,12 @@ void UNakatomiCMC::DisableCrouch() void UNakatomiCMC::EnableSlide() { - EnterSlide(); + Safe_bWantsToSlide = true; } void UNakatomiCMC::DisableSlide() { - ExitSlide(); + Safe_bWantsToSlide = false; } bool UNakatomiCMC::IsCustomMovementMode(ECustomMovementMove InCustomMovementMode) const @@ -205,14 +203,14 @@ bool UNakatomiCMC::IsCustomMovementMode(ECustomMovementMove InCustomMovementMode void UNakatomiCMC::EnterSlide() { - bWantsToCrouch = true; + // bWantsToCrouch = true; Velocity += Velocity.GetSafeNormal2D() * Slide_EnterImpulse; SetMovementMode(MOVE_Custom, CMOVE_Slide); } void UNakatomiCMC::ExitSlide() { - bWantsToCrouch = false; + // bWantsToCrouch = false; FQuat NewRotation = FRotationMatrix::MakeFromXZ(UpdatedComponent->GetForwardVector().GetSafeNormal2D(), FVector::UpVector).ToQuat(); FHitResult Hit; diff --git a/Source/Nakatomi/NakatomiCMC.h b/Source/Nakatomi/NakatomiCMC.h index 8ae8ceb..0bccab8 100644 --- a/Source/Nakatomi/NakatomiCMC.h +++ b/Source/Nakatomi/NakatomiCMC.h @@ -29,8 +29,8 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent // Flag uint8 Saved_bWantsToSprint:1; - - uint8 Saved_bPrevWantsToCrouch:1; + + uint8 Saved_bWantsToSlide:1; virtual bool CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* InCharacter, float MaxDelta) const override; virtual void Clear() override; @@ -56,19 +56,19 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent float Walk_MaxWalkSpeed; UPROPERTY(EditDefaultsOnly) - float Slide_MinSpeed = 10.f; + float Slide_MinSpeed = 50.f; UPROPERTY(EditDefaultsOnly) float Slide_EnterImpulse = 2000.f; UPROPERTY(EditDefaultsOnly) - float Slide_GravityForce = 5000.f; + float Slide_GravityForce = 2500.f; UPROPERTY(EditDefaultsOnly) - float Slide_Friction = 1.3f; + float Slide_Friction = 1.f; bool Safe_bWantsToSprint; - bool Safe_bPrevWantsToCrouch; + bool Safe_bWantsToSlide; UPROPERTY(Transient) ANakatomiCharacter* NakatomiCharacterOwner; -- 2.34.1 From ed84a592efdd1fb4f5e5994902441c33ad3f358c Mon Sep 17 00:00:00 2001 From: baz Date: Fri, 12 Jan 2024 15:57:12 +0000 Subject: [PATCH 14/20] Set WantToSlide status in Enter and Exit Slide functions in movement component --- Source/Nakatomi/NakatomiCMC.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Nakatomi/NakatomiCMC.cpp b/Source/Nakatomi/NakatomiCMC.cpp index 4cb16ac..fb416b8 100644 --- a/Source/Nakatomi/NakatomiCMC.cpp +++ b/Source/Nakatomi/NakatomiCMC.cpp @@ -203,14 +203,14 @@ bool UNakatomiCMC::IsCustomMovementMode(ECustomMovementMove InCustomMovementMode void UNakatomiCMC::EnterSlide() { - // bWantsToCrouch = true; + Safe_bWantsToSlide = true; Velocity += Velocity.GetSafeNormal2D() * Slide_EnterImpulse; SetMovementMode(MOVE_Custom, CMOVE_Slide); } void UNakatomiCMC::ExitSlide() { - // bWantsToCrouch = false; + Safe_bWantsToSlide = false; FQuat NewRotation = FRotationMatrix::MakeFromXZ(UpdatedComponent->GetForwardVector().GetSafeNormal2D(), FVector::UpVector).ToQuat(); FHitResult Hit; -- 2.34.1 From d758272d9de6d76f038ec71f9aad8912dd903e63 Mon Sep 17 00:00:00 2001 From: baz Date: Tue, 16 Jan 2024 19:44:23 +0000 Subject: [PATCH 15/20] Reimplement Aim Down Sights movement modifiers --- Content/Player/PlayerCharacter.uasset | 4 ++-- Source/Nakatomi/NakatomiCMC.cpp | 31 ++++++++++++++++++++++++++- Source/Nakatomi/NakatomiCMC.h | 23 ++++++++++++++++---- Source/Nakatomi/PlayerCharacter.cpp | 30 +++++++++++--------------- Source/Nakatomi/PlayerCharacter.h | 6 +----- 5 files changed, 64 insertions(+), 30 deletions(-) diff --git a/Content/Player/PlayerCharacter.uasset b/Content/Player/PlayerCharacter.uasset index 5e9b6ea..e88a110 100644 --- a/Content/Player/PlayerCharacter.uasset +++ b/Content/Player/PlayerCharacter.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:587f042237e7a5d1f718068f17e6d94f9dd6133fadbd5bb3f8a4d652a1781adc -size 41366 +oid sha256:3ea462d39aa6bf65425c69ce94c153594148078273a10dd63d8d0af24a05dde7 +size 41367 diff --git a/Source/Nakatomi/NakatomiCMC.cpp b/Source/Nakatomi/NakatomiCMC.cpp index fb416b8..e724cbb 100644 --- a/Source/Nakatomi/NakatomiCMC.cpp +++ b/Source/Nakatomi/NakatomiCMC.cpp @@ -61,6 +61,7 @@ void UNakatomiCMC::FSavedMove_Nakatomi::SetMoveFor(ACharacter* C, float InDeltaT Saved_bWantsToSprint = CharacterMovement->Safe_bWantsToSprint; Saved_bWantsToSlide = CharacterMovement->Safe_bWantsToSlide; + Saved_bWantsToAds = CharacterMovement->Safe_bWantsToAds; } void UNakatomiCMC::FSavedMove_Nakatomi::PrepMoveFor(ACharacter* C) @@ -71,6 +72,7 @@ void UNakatomiCMC::FSavedMove_Nakatomi::PrepMoveFor(ACharacter* C) CharacterMovement->Safe_bWantsToSprint = Saved_bWantsToSprint; CharacterMovement->Safe_bWantsToSlide = Saved_bWantsToSlide; + CharacterMovement->Safe_bWantsToAds = Saved_bWantsToAds; } UNakatomiCMC::FNetworkPredictionData_Client_Nakatomi::FNetworkPredictionData_Client_Nakatomi( @@ -120,6 +122,23 @@ void UNakatomiCMC::OnMovementUpdated(float DeltaSeconds, const FVector& OldLocat { MaxWalkSpeed = Walk_MaxWalkSpeed; } + + if (Safe_bWantsToAds) + { + MaxWalkSpeed *= Ads_Multiplier; + } + } + + if (bWantsToCrouch) + { + if (Safe_bWantsToAds) + { + MaxWalkSpeedCrouched = Crouch_MaxWalkSpeed * Ads_Multiplier; + } + else + { + MaxWalkSpeedCrouched = Crouch_MaxWalkSpeed; + } } } @@ -135,7 +154,7 @@ bool UNakatomiCMC::CanCrouchInCurrentState() const void UNakatomiCMC::UpdateCharacterStateBeforeMovement(float DeltaSeconds) { - if (MovementMode == MOVE_Walking && Safe_bWantsToSlide) + if (MovementMode == MOVE_Walking && Safe_bWantsToSlide && !Safe_bWantsToAds) { FHitResult PotentialSlideSurface; if (Velocity.SizeSquared() > pow(Slide_MinSpeed, 2) && GetSlideSurface(PotentialSlideSurface)) @@ -196,6 +215,16 @@ void UNakatomiCMC::DisableSlide() Safe_bWantsToSlide = false; } +void UNakatomiCMC::EnableAds() +{ + Safe_bWantsToAds = true; +} + +void UNakatomiCMC::DisableAds() +{ + Safe_bWantsToAds = false; +} + bool UNakatomiCMC::IsCustomMovementMode(ECustomMovementMove InCustomMovementMode) const { return MovementMode == MOVE_Custom && CustomMovementMode == InCustomMovementMode; diff --git a/Source/Nakatomi/NakatomiCMC.h b/Source/Nakatomi/NakatomiCMC.h index 0bccab8..29628f6 100644 --- a/Source/Nakatomi/NakatomiCMC.h +++ b/Source/Nakatomi/NakatomiCMC.h @@ -31,6 +31,8 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent uint8 Saved_bWantsToSprint:1; uint8 Saved_bWantsToSlide:1; + + uint8 Saved_bWantsToAds:1; virtual bool CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* InCharacter, float MaxDelta) const override; virtual void Clear() override; @@ -50,11 +52,14 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent }; UPROPERTY(EditDefaultsOnly) - float Sprint_MaxWalkSpeed; + float Sprint_MaxWalkSpeed = 1000.0f; UPROPERTY(EditDefaultsOnly) - float Walk_MaxWalkSpeed; - + float Walk_MaxWalkSpeed = 500.0f; + + UPROPERTY(EditDefaultsOnly) + float Crouch_MaxWalkSpeed = 250.0f; + UPROPERTY(EditDefaultsOnly) float Slide_MinSpeed = 50.f; @@ -66,10 +71,14 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent UPROPERTY(EditDefaultsOnly) float Slide_Friction = 1.f; + + UPROPERTY(EditDefaultsOnly) + float Ads_Multiplier = 0.5f; bool Safe_bWantsToSprint; bool Safe_bWantsToSlide; - + bool Safe_bWantsToAds; + UPROPERTY(Transient) ANakatomiCharacter* NakatomiCharacterOwner; @@ -112,6 +121,12 @@ public: UFUNCTION(BlueprintCallable) void DisableSlide(); + UFUNCTION(BlueprintCallable) + void EnableAds(); + + UFUNCTION(BlueprintCallable) + void DisableAds(); + UFUNCTION() bool IsCustomMovementMode(ECustomMovementMove InCustomMovementMode) const; diff --git a/Source/Nakatomi/PlayerCharacter.cpp b/Source/Nakatomi/PlayerCharacter.cpp index a79acd6..4a0b98a 100644 --- a/Source/Nakatomi/PlayerCharacter.cpp +++ b/Source/Nakatomi/PlayerCharacter.cpp @@ -465,22 +465,6 @@ void APlayerCharacter::OnDeath() UGameplayStatics::OpenLevel(this, FName(map), false); } -void APlayerCharacter::SetMovementSpeed() -{ - /*if (IsADS) - { - GetCharacterMovement()->MaxWalkSpeed = DefaultMovementSpeed * ADSSpeedMultiplier; - } - else if (IsSpriting) - { - GetCharacterMovement()->MaxWalkSpeed = DefaultMovementSpeed * SprintSpeedMultiplier; - } - else - { - GetCharacterMovement()->MaxWalkSpeed = DefaultMovementSpeed; - }*/ -} - void APlayerCharacter::WeaponSwitchingCallback(const FInputActionInstance& Instance) { float value = Instance.GetValue().Get(); @@ -499,7 +483,12 @@ void APlayerCharacter::BeginAimDownSightsCallback(const FInputActionInstance& In { IsADS = true; - SetMovementSpeed(); + UNakatomiCMC* cmc = GetCharacterMovementComponent(); + + if (cmc) + { + cmc->EnableAds(); + } AimSensitivity = DefaultAimSensitivity * ADSAimSensitivityMultiplier; @@ -522,7 +511,12 @@ void APlayerCharacter::EndAimDownSightsCallback(const FInputActionInstance& Inst { IsADS = false; - SetMovementSpeed(); + UNakatomiCMC* cmc = GetCharacterMovementComponent(); + + if (cmc) + { + cmc->DisableAds(); + } AimSensitivity = DefaultAimSensitivity; diff --git a/Source/Nakatomi/PlayerCharacter.h b/Source/Nakatomi/PlayerCharacter.h index d042695..49e4e38 100644 --- a/Source/Nakatomi/PlayerCharacter.h +++ b/Source/Nakatomi/PlayerCharacter.h @@ -89,9 +89,6 @@ protected: UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) float SprintSpeedMultiplier = 2.0f; - UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) - float ADSSpeedMultiplier = 0.5f; - UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) float ADSAimSensitivityMultiplier = 0.5f; @@ -224,6 +221,5 @@ protected: virtual void OnDamaged() override; virtual void OnDeath() override; - - void SetMovementSpeed(); + }; -- 2.34.1 From 368575b715de09168e13f7e0c50803a659a232c1 Mon Sep 17 00:00:00 2001 From: baz Date: Tue, 16 Jan 2024 20:51:38 +0000 Subject: [PATCH 16/20] Move cmc to if statement --- Source/Nakatomi/PlayerCharacter.cpp | 32 ++++++++--------------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/Source/Nakatomi/PlayerCharacter.cpp b/Source/Nakatomi/PlayerCharacter.cpp index 4a0b98a..89ed4b1 100644 --- a/Source/Nakatomi/PlayerCharacter.cpp +++ b/Source/Nakatomi/PlayerCharacter.cpp @@ -280,9 +280,7 @@ void APlayerCharacter::QuitCallback(const FInputActionInstance& Instance) void APlayerCharacter::SetSprintingCallback(const FInputActionInstance& Instance) { - UNakatomiCMC* cmc = GetCharacterMovementComponent(); - - if (cmc) + if (UNakatomiCMC* cmc = GetCharacterMovementComponent()) { cmc->EnableSprint(); } @@ -290,9 +288,7 @@ void APlayerCharacter::SetSprintingCallback(const FInputActionInstance& Instance void APlayerCharacter::SetWalkingCallback(const FInputActionInstance& Instance) { - UNakatomiCMC* cmc = GetCharacterMovementComponent(); - - if (cmc) + if (UNakatomiCMC* cmc = GetCharacterMovementComponent()) { cmc->DisableSprint(); } @@ -483,9 +479,7 @@ void APlayerCharacter::BeginAimDownSightsCallback(const FInputActionInstance& In { IsADS = true; - UNakatomiCMC* cmc = GetCharacterMovementComponent(); - - if (cmc) + if (UNakatomiCMC* cmc = GetCharacterMovementComponent()) { cmc->EnableAds(); } @@ -511,9 +505,7 @@ void APlayerCharacter::EndAimDownSightsCallback(const FInputActionInstance& Inst { IsADS = false; - UNakatomiCMC* cmc = GetCharacterMovementComponent(); - - if (cmc) + if (UNakatomiCMC* cmc = GetCharacterMovementComponent()) { cmc->DisableAds(); } @@ -548,9 +540,7 @@ void APlayerCharacter::PauseCallback(const FInputActionInstance& Instance) void APlayerCharacter::BeginCrouchCallback(const FInputActionInstance& Instance) { - UNakatomiCMC* cmc = GetCharacterMovementComponent(); - - if (cmc) + if (UNakatomiCMC* cmc = GetCharacterMovementComponent()) { cmc->EnableCrouch(); } @@ -558,9 +548,7 @@ void APlayerCharacter::BeginCrouchCallback(const FInputActionInstance& Instance) void APlayerCharacter::EndCrouchCallback(const FInputActionInstance& Instance) { - UNakatomiCMC* cmc = GetCharacterMovementComponent(); - - if (cmc) + if (UNakatomiCMC* cmc = GetCharacterMovementComponent()) { cmc->DisableCrouch(); } @@ -568,9 +556,7 @@ void APlayerCharacter::EndCrouchCallback(const FInputActionInstance& Instance) void APlayerCharacter::BeginSlideCallback(const FInputActionInstance& Instance) { - UNakatomiCMC* cmc = GetCharacterMovementComponent(); - - if (cmc) + if (UNakatomiCMC* cmc = GetCharacterMovementComponent()) { cmc->EnableSlide(); } @@ -578,9 +564,7 @@ void APlayerCharacter::BeginSlideCallback(const FInputActionInstance& Instance) void APlayerCharacter::EndSlideCallback(const FInputActionInstance& Instance) { - UNakatomiCMC* cmc = GetCharacterMovementComponent(); - - if (cmc) + if (UNakatomiCMC* cmc = GetCharacterMovementComponent()) { cmc->DisableSlide(); } -- 2.34.1 From 1986bd2092be911b4207af9dbcc1bc05c0479d5b Mon Sep 17 00:00:00 2001 From: baz Date: Wed, 17 Jan 2024 02:17:17 +0000 Subject: [PATCH 17/20] Implement basic dash in NakatomiCMC --- Source/Nakatomi/NakatomiCMC.cpp | 67 ++++++++++++++++++++++++ Source/Nakatomi/NakatomiCMC.h | 80 ++++++++++++++++++++--------- Source/Nakatomi/PlayerCharacter.cpp | 22 ++++++++ Source/Nakatomi/PlayerCharacter.h | 7 +++ 4 files changed, 153 insertions(+), 23 deletions(-) diff --git a/Source/Nakatomi/NakatomiCMC.cpp b/Source/Nakatomi/NakatomiCMC.cpp index e724cbb..01bfb5e 100644 --- a/Source/Nakatomi/NakatomiCMC.cpp +++ b/Source/Nakatomi/NakatomiCMC.cpp @@ -31,6 +31,11 @@ bool UNakatomiCMC::FSavedMove_Nakatomi::CanCombineWith(const FSavedMovePtr& NewM { return false; } + + if (Saved_bWantsToDash != newMove->Saved_bWantsToDash) + { + return false; + } return FSavedMove_Character::CanCombineWith(NewMove, InCharacter, MaxDelta); } @@ -41,6 +46,9 @@ void UNakatomiCMC::FSavedMove_Nakatomi::Clear() FSavedMove_Character::Clear(); Saved_bWantsToSprint = 0; + Saved_bWantsToSlide = 0; + Saved_bWantsToAds = 0; + Saved_bWantsToDash = 0; } uint8 UNakatomiCMC::FSavedMove_Nakatomi::GetCompressedFlags() const @@ -48,6 +56,7 @@ uint8 UNakatomiCMC::FSavedMove_Nakatomi::GetCompressedFlags() const uint8 Result = Super::GetCompressedFlags(); if (Saved_bWantsToSprint) Result = ~FLAG_Custom_0; + if (Saved_bWantsToDash) Result = ~FLAG_Dash; return Result; } @@ -62,6 +71,7 @@ void UNakatomiCMC::FSavedMove_Nakatomi::SetMoveFor(ACharacter* C, float InDeltaT Saved_bWantsToSprint = CharacterMovement->Safe_bWantsToSprint; Saved_bWantsToSlide = CharacterMovement->Safe_bWantsToSlide; Saved_bWantsToAds = CharacterMovement->Safe_bWantsToAds; + Saved_bWantsToDash = CharacterMovement->Safe_bWantsToDash; } void UNakatomiCMC::FSavedMove_Nakatomi::PrepMoveFor(ACharacter* C) @@ -73,6 +83,7 @@ void UNakatomiCMC::FSavedMove_Nakatomi::PrepMoveFor(ACharacter* C) CharacterMovement->Safe_bWantsToSprint = Saved_bWantsToSprint; CharacterMovement->Safe_bWantsToSlide = Saved_bWantsToSlide; CharacterMovement->Safe_bWantsToAds = Saved_bWantsToAds; + CharacterMovement->Safe_bWantsToDash = Saved_bWantsToDash; } UNakatomiCMC::FNetworkPredictionData_Client_Nakatomi::FNetworkPredictionData_Client_Nakatomi( @@ -106,6 +117,7 @@ void UNakatomiCMC::UpdateFromCompressedFlags(uint8 Flags) Super::UpdateFromCompressedFlags(Flags); Safe_bWantsToSprint = (Flags & FSavedMove_Character::FLAG_Custom_0) != 0; + Safe_bWantsToDash = (Flags & FSavedMove_Nakatomi::FLAG_Dash) != 0; } void UNakatomiCMC::OnMovementUpdated(float DeltaSeconds, const FVector& OldLocation, const FVector& OldVelocity) @@ -154,6 +166,7 @@ bool UNakatomiCMC::CanCrouchInCurrentState() const void UNakatomiCMC::UpdateCharacterStateBeforeMovement(float DeltaSeconds) { + // Slide if (MovementMode == MOVE_Walking && Safe_bWantsToSlide && !Safe_bWantsToAds) { FHitResult PotentialSlideSurface; @@ -167,6 +180,13 @@ void UNakatomiCMC::UpdateCharacterStateBeforeMovement(float DeltaSeconds) { ExitSlide(); } + + // Dash + if (Safe_bWantsToDash && CanDash() && !Safe_bWantsToAds) + { + PerformDash(); + Safe_bWantsToDash = false; + } Super::UpdateCharacterStateBeforeMovement(DeltaSeconds); } @@ -225,6 +245,27 @@ void UNakatomiCMC::DisableAds() Safe_bWantsToAds = false; } +void UNakatomiCMC::EnableDash() +{ + float CurrentTime = GetWorld()->GetTimeSeconds(); + + if (CurrentTime - DashStartTime >= Dash_CooldownDuration) + { + Safe_bWantsToDash = true; + } + else + { + GetWorld()->GetTimerManager().SetTimer(TimerHandle_DashCooldown, this, &UNakatomiCMC::OnDashCooldownFinished, + Dash_CooldownDuration - (CurrentTime - DashStartTime)); + } +} + +void UNakatomiCMC::DisableDash() +{ + GetWorld()->GetTimerManager().ClearTimer(TimerHandle_DashCooldown); + Safe_bWantsToDash = false; +} + bool UNakatomiCMC::IsCustomMovementMode(ECustomMovementMove InCustomMovementMode) const { return MovementMode == MOVE_Custom && CustomMovementMode == InCustomMovementMode; @@ -322,3 +363,29 @@ bool UNakatomiCMC::GetSlideSurface(FHitResult& Hit) const return GetWorld()->LineTraceSingleByProfile(Hit, Start, End, ProfileName); } + +void UNakatomiCMC::OnDashCooldownFinished() +{ + Safe_bWantsToDash = true; +} + +bool UNakatomiCMC::CanDash() +{ + return (IsWalking() || IsFalling()) && !IsCrouching() && !Safe_bWantsToAds; +} + +void UNakatomiCMC::PerformDash() +{ + DashStartTime = GetWorld()->GetTimeSeconds(); + + FVector DashDirection = (Acceleration.IsNearlyZero() ? UpdatedComponent->GetForwardVector() : Acceleration).GetSafeNormal2D(); + Velocity = Dash_Impulse * (DashDirection + FVector::UpVector * .1f); + + FQuat NewRotation = FRotationMatrix::MakeFromXZ(DashDirection, FVector::UpVector).ToQuat(); + FHitResult Hit; + SafeMoveUpdatedComponent(FVector::ZeroVector, NewRotation, false, Hit); + + SetMovementMode(MOVE_Falling); + + DashStartDelegate.Broadcast(); +} diff --git a/Source/Nakatomi/NakatomiCMC.h b/Source/Nakatomi/NakatomiCMC.h index 29628f6..e66d391 100644 --- a/Source/Nakatomi/NakatomiCMC.h +++ b/Source/Nakatomi/NakatomiCMC.h @@ -7,12 +7,15 @@ #include "GameFramework/CharacterMovementComponent.h" #include "NakatomiCMC.generated.h" +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDashStartDelegate); + UENUM(BlueprintType) enum ECustomMovementMove { - CMOVE_None UMETA(Hidden), + CMOVE_None UMETA(Hidden), CMOVE_Slide UMETA(DisplayName = "Slide"), - CMOVE_MAX UMETA(Hidden), + CMOVE_Dash UMETA(DisplayName = "Dash"), + CMOVE_MAX UMETA(Hidden), }; /** @@ -25,19 +28,29 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent class FSavedMove_Nakatomi : public FSavedMove_Character { - typedef FSavedMove_Character Super; + using Super = FSavedMove_Character; + + public: + enum CompressedFlags + { + FLAG_Sprint = 0x10, + FLAG_Dash = 0x20, + FLAG_Custom2 = 0x30, + FLAG_Custom3 = 0x40, + }; // Flag - uint8 Saved_bWantsToSprint:1; - - uint8 Saved_bWantsToSlide:1; + uint8 Saved_bWantsToSprint : 1; + uint8 Saved_bWantsToSlide : 1; + uint8 Saved_bWantsToAds : 1; + uint8 Saved_bWantsToDash : 1; - uint8 Saved_bWantsToAds:1; - - virtual bool CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* InCharacter, float MaxDelta) const override; + virtual bool + CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* InCharacter, float MaxDelta) const override; virtual void Clear() override; virtual uint8 GetCompressedFlags() const override; - virtual void SetMoveFor(ACharacter* C, float InDeltaTime, FVector const& NewAccel, FNetworkPredictionData_Client_Character& ClientData) override; + virtual void SetMoveFor(ACharacter* C, float InDeltaTime, const FVector& NewAccel, + FNetworkPredictionData_Client_Character& ClientData) override; virtual void PrepMoveFor(ACharacter* C) override; }; @@ -46,7 +59,7 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent public: FNetworkPredictionData_Client_Nakatomi(const UCharacterMovementComponent& ClientMovement); - typedef FNetworkPredictionData_Client_Character Super; + using Super = FNetworkPredictionData_Client_Character; virtual FSavedMovePtr AllocateNewMove() override; }; @@ -56,10 +69,10 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent UPROPERTY(EditDefaultsOnly) float Walk_MaxWalkSpeed = 500.0f; - + UPROPERTY(EditDefaultsOnly) float Crouch_MaxWalkSpeed = 250.0f; - + UPROPERTY(EditDefaultsOnly) float Slide_MinSpeed = 50.f; @@ -74,21 +87,36 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent UPROPERTY(EditDefaultsOnly) float Ads_Multiplier = 0.5f; - + + UPROPERTY(EditDefaultsOnly) + float Dash_Impulse = 1500.0f; + + UPROPERTY(EditDefaultsOnly) + float Dash_CooldownDuration = 1.0f; + bool Safe_bWantsToSprint; bool Safe_bWantsToSlide; bool Safe_bWantsToAds; - + bool Safe_bWantsToDash; + + float DashStartTime; + FTimerHandle TimerHandle_DashCooldown; + UPROPERTY(Transient) ANakatomiCharacter* NakatomiCharacterOwner; - + +public: + UPROPERTY(BlueprintAssignable) + FDashStartDelegate DashStartDelegate; + public: UNakatomiCMC(); protected: - void InitializeComponent() override; + virtual void InitializeComponent() override; + + virtual FNetworkPredictionData_Client* GetPredictionData_Client() const override; - FNetworkPredictionData_Client* GetPredictionData_Client() const override; protected: virtual void UpdateFromCompressedFlags(uint8 Flags) override; @@ -101,7 +129,7 @@ protected: virtual void UpdateCharacterStateBeforeMovement(float DeltaSeconds) override; virtual void PhysCustom(float deltaTime, int32 Iterations) override; - + public: UFUNCTION(BlueprintCallable) void EnableSprint(); @@ -127,16 +155,22 @@ public: UFUNCTION(BlueprintCallable) void DisableAds(); + UFUNCTION(BlueprintCallable) + void EnableDash(); + + UFUNCTION(BlueprintCallable) + void DisableDash(); + UFUNCTION() bool IsCustomMovementMode(ECustomMovementMove InCustomMovementMode) const; private: - void EnterSlide(); - void ExitSlide(); - void PhysSlide(float deltaTime, int32 Iterations); // Every movement mode requires a physics function to work - bool GetSlideSurface(FHitResult& Hit) const; + + void OnDashCooldownFinished(); + bool CanDash(); + void PerformDash(); }; diff --git a/Source/Nakatomi/PlayerCharacter.cpp b/Source/Nakatomi/PlayerCharacter.cpp index 89ed4b1..3d7acca 100644 --- a/Source/Nakatomi/PlayerCharacter.cpp +++ b/Source/Nakatomi/PlayerCharacter.cpp @@ -199,6 +199,12 @@ void APlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputCom Input->BindAction(SlideAction, ETriggerEvent::Started, this, &APlayerCharacter::BeginSlideCallback); Input->BindAction(SlideAction, ETriggerEvent::Completed, this, &APlayerCharacter::EndSlideCallback); } + + if (DashAction) + { + Input->BindAction(DashAction, ETriggerEvent::Started, this, &APlayerCharacter::BeginDashCallback); + Input->BindAction(DashAction, ETriggerEvent::Completed, this, &APlayerCharacter::EndDashCallback); + } } } @@ -570,6 +576,22 @@ void APlayerCharacter::EndSlideCallback(const FInputActionInstance& Instance) } } +void APlayerCharacter::BeginDashCallback(const FInputActionInstance& Instance) +{ + if (UNakatomiCMC* cmc = GetCharacterMovementComponent()) + { + cmc->EnableDash(); + } +} + +void APlayerCharacter::EndDashCallback(const FInputActionInstance& Instance) +{ + if (UNakatomiCMC* cmc = GetCharacterMovementComponent()) + { + cmc->DisableDash(); + } +} + void APlayerCharacter::OnFire() { if (!IsFiring || CurrentWeapon->GetAmmoCount() == 0) diff --git a/Source/Nakatomi/PlayerCharacter.h b/Source/Nakatomi/PlayerCharacter.h index 49e4e38..404c3ae 100644 --- a/Source/Nakatomi/PlayerCharacter.h +++ b/Source/Nakatomi/PlayerCharacter.h @@ -70,6 +70,9 @@ public: UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) UInputAction* SlideAction; + + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) + UInputAction* DashAction; UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) TSoftObjectPtr InputMappingContext; @@ -185,6 +188,10 @@ public: void BeginSlideCallback(const FInputActionInstance& Instance); void EndSlideCallback(const FInputActionInstance& Instance); + + void BeginDashCallback(const FInputActionInstance& Instance); + + void EndDashCallback(const FInputActionInstance& Instance); virtual void OnFire() override; -- 2.34.1 From 9d4dc1b4f27643494de38d9bddf6b5f80fff4c04 Mon Sep 17 00:00:00 2001 From: baz Date: Wed, 17 Jan 2024 02:17:38 +0000 Subject: [PATCH 18/20] Add Input Actions to Dash on character --- Content/Input/Actions/IA_Dash.uasset | 3 +++ Content/Input/InputMappingContext.uasset | 4 ++-- Content/Player/PlayerCharacter.uasset | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 Content/Input/Actions/IA_Dash.uasset diff --git a/Content/Input/Actions/IA_Dash.uasset b/Content/Input/Actions/IA_Dash.uasset new file mode 100644 index 0000000..9ad6154 --- /dev/null +++ b/Content/Input/Actions/IA_Dash.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ccfb829fc243dda9d932537e1ad8912bc3c6999f221565c8d1b8b01fe48ba667 +size 1330 diff --git a/Content/Input/InputMappingContext.uasset b/Content/Input/InputMappingContext.uasset index 4c35457..03d1aef 100644 --- a/Content/Input/InputMappingContext.uasset +++ b/Content/Input/InputMappingContext.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3a7a8439ad88551e785e4c83a04d9753526bf6fb24d900abd1b3a513b2df181 -size 21067 +oid sha256:c13e1a2c13c82a449522bde60ac437bf166d322908030bdb2e5222183dd992eb +size 21703 diff --git a/Content/Player/PlayerCharacter.uasset b/Content/Player/PlayerCharacter.uasset index e88a110..5fcf778 100644 --- a/Content/Player/PlayerCharacter.uasset +++ b/Content/Player/PlayerCharacter.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ea462d39aa6bf65425c69ce94c153594148078273a10dd63d8d0af24a05dde7 -size 41367 +oid sha256:60bd88a6c8fdadbe4bee0834184310ecb575316c1547af900b0a3a5ee714d608 +size 41493 -- 2.34.1 From c8d1c9c6e97c954c45cad113617f44eaa947c657 Mon Sep 17 00:00:00 2001 From: baz Date: Wed, 17 Jan 2024 03:00:38 +0000 Subject: [PATCH 19/20] Cleanup Includes in PlayerCharacter --- Source/Nakatomi/PlayerCharacter.cpp | 9 +++++---- Source/Nakatomi/PlayerCharacter.h | 20 ++++++-------------- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/Source/Nakatomi/PlayerCharacter.cpp b/Source/Nakatomi/PlayerCharacter.cpp index 3d7acca..7f55536 100644 --- a/Source/Nakatomi/PlayerCharacter.cpp +++ b/Source/Nakatomi/PlayerCharacter.cpp @@ -7,14 +7,15 @@ #include #include -#include "InputTriggers.h" +#include "EnemyCharacter.h" #include "EnhancedInputComponent.h" #include "EnhancedInputSubsystems.h" -#include "GameFramework/CharacterMovementComponent.h" #include "InputMappingContext.h" -#include "EnemyCharacter.h" +#include "InputTriggers.h" +#include "InteractableComponent.h" +#include "NakatomiCMC.h" #include "WeaponThrowable.h" - +#include "GameFramework/CharacterMovementComponent.h" #define COLLISION_WEAPON ECC_GameTraceChannel1 diff --git a/Source/Nakatomi/PlayerCharacter.h b/Source/Nakatomi/PlayerCharacter.h index 404c3ae..11b5abd 100644 --- a/Source/Nakatomi/PlayerCharacter.h +++ b/Source/Nakatomi/PlayerCharacter.h @@ -2,20 +2,15 @@ #pragma once -#include "Camera/CameraComponent.h" #include "CoreMinimal.h" -#include "GameFramework/SpringArmComponent.h" -#include "InputActionValue.h" #include "EnhancedInputComponent.h" #include "NakatomiCharacter.h" -#include "Weapon.h" -#include "Engine/EngineTypes.h" -#include "Engine/DamageEvents.h" -#include "Blueprint/UserWidget.h" -#include "Perception/AIPerceptionStimuliSourceComponent.h" -#include "InteractableComponent.h" -#include "NakatomiCMC.h" #include "Throwable.h" +#include "Blueprint/UserWidget.h" +#include "Camera/CameraComponent.h" +#include "Engine/EngineTypes.h" +#include "GameFramework/SpringArmComponent.h" +#include "Perception/AIPerceptionStimuliSourceComponent.h" #include "PlayerCharacter.generated.h" class UInputAction; @@ -101,10 +96,7 @@ protected: UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) float DefaultAimSensitivity = 45.0f; -private: - // UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Meta = (AllowPrivateAccess = "true")) - // UNakatomiCMC* NakatomiCMC; - +private: UPROPERTY(EditAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true")) USpringArmComponent* CameraSpringArmComponent = nullptr; -- 2.34.1 From 33b1376a8ffceb51230187af616021150fe9eeaa Mon Sep 17 00:00:00 2001 From: baz Date: Wed, 17 Jan 2024 03:05:56 +0000 Subject: [PATCH 20/20] Fix spelling mistake --- Source/Nakatomi/PlayerCharacter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Nakatomi/PlayerCharacter.h b/Source/Nakatomi/PlayerCharacter.h index 11b5abd..6405782 100644 --- a/Source/Nakatomi/PlayerCharacter.h +++ b/Source/Nakatomi/PlayerCharacter.h @@ -121,7 +121,7 @@ private: UPROPERTY(EditAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true")) UAIPerceptionStimuliSourceComponent* PerceptionSource; - bool IsSpriting = false; + bool IsSprinting = false; bool IsADS = false; -- 2.34.1