Implement basic dash in NakatomiCMC

This commit is contained in:
baz 2024-01-17 02:17:17 +00:00
parent 368575b715
commit 1986bd2092
4 changed files with 153 additions and 23 deletions

View File

@ -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();
}

View File

@ -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();
};

View File

@ -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)

View File

@ -70,6 +70,9 @@ public:
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
UInputAction* SlideAction;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
UInputAction* DashAction;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
TSoftObjectPtr<UInputMappingContext> 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;