Implemented AMyVICharacterBase
This commit is contained in:
parent
e2a109255b
commit
f6d54647aa
BIN
EndlessVendetta/Content/FirstPersonArms/Character/Mesh/SK_Mannequin_Arms_Skeleton.uasset
(Stored with Git LFS)
BIN
EndlessVendetta/Content/FirstPersonArms/Character/Mesh/SK_Mannequin_Arms_Skeleton.uasset
(Stored with Git LFS)
Binary file not shown.
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:23f1d30713deb7b63e333e5bffd36f97365280f94c773c2b5a1128418a658c42
|
||||
oid sha256:928263e4929943c3bca1c28ad56a4a5530a5a7e2318a11275415abcb276a0e15
|
||||
size 679253
|
||||
|
BIN
EndlessVendetta/Content/StarterContent/Blueprints/Blueprint_CeilingLight.uasset
(Stored with Git LFS)
BIN
EndlessVendetta/Content/StarterContent/Blueprints/Blueprint_CeilingLight.uasset
(Stored with Git LFS)
Binary file not shown.
BIN
EndlessVendetta/Content/StarterContent/HDRI/HDRI_Epic_Courtyard_Daylight.uasset
(Stored with Git LFS)
BIN
EndlessVendetta/Content/StarterContent/HDRI/HDRI_Epic_Courtyard_Daylight.uasset
(Stored with Git LFS)
Binary file not shown.
@ -23,6 +23,11 @@
|
||||
"TargetAllowList": [
|
||||
"Editor"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "VaultIt",
|
||||
"Enabled": true,
|
||||
"MarketplaceURL": "com.epicgames.launcher://ue/marketplace/content/7d19b5622d6846edb9881e6c89bce05e"
|
||||
}
|
||||
]
|
||||
}
|
@ -12,7 +12,7 @@ public class EndlessVendetta : ModuleRules
|
||||
{
|
||||
"Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "EnhancedInput", "AIModule",
|
||||
"GameplayTasks", "NavigationSystem", "UMG", "Slate", "SlateCore", "Niagara", "NiagaraCore", "NiagaraShader",
|
||||
"HTTP", "Json", "JsonUtilities"
|
||||
"HTTP", "Json", "JsonUtilities", "VaultIt", "MotionWarping", "GameplayAbilities"
|
||||
});
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@
|
||||
#include "Components/ArrowComponent.h"
|
||||
#include "GadgetSystem/GadgetManager.h"
|
||||
#include "Inventory/InventoryComponent.h"
|
||||
#include "Pawn/VICharacter.h"
|
||||
|
||||
#include "EndlessVendettaCharacter.generated.h"
|
||||
|
||||
|
309
EndlessVendetta/Source/EndlessVendetta/MyVICharacterBase.cpp
Normal file
309
EndlessVendetta/Source/EndlessVendetta/MyVICharacterBase.cpp
Normal file
@ -0,0 +1,309 @@
|
||||
// Copyright (c) 2019-2022 Drowning Dragons Limited. All Rights Reserved.
|
||||
|
||||
#include "EndlessVendetta/MyVICharacterBase.h"
|
||||
#include "Pawn/VICharacterBase.h"
|
||||
#include "Net/UnrealNetwork.h"
|
||||
#include "GameFramework/CharacterMovementComponent.h"
|
||||
#include "Pawn/VIPawnVaultComponent.h"
|
||||
#include "MotionWarpingComponent.h"
|
||||
#include "VIBlueprintFunctionLibrary.h"
|
||||
|
||||
void AMyVICharacterBase::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
VaultComponent = IVIPawnInterface::Execute_GetPawnVaultComponent(this);
|
||||
MotionWarpingComponent = IVIPawnInterface::Execute_GetMotionWarpingComponent(this);
|
||||
}
|
||||
|
||||
void AMyVICharacterBase::CheckJumpInput(float DeltaTime)
|
||||
{
|
||||
const bool bIsVaulting = IsVaulting();
|
||||
|
||||
// Server update simulated proxies with correct vaulting state
|
||||
if (GetLocalRole() == ROLE_Authority && GetNetMode() != NM_Standalone)
|
||||
{
|
||||
bRepIsVaulting = bIsVaulting;
|
||||
}
|
||||
|
||||
// Try to vault from local input
|
||||
if (IsLocallyControlled() && VaultComponent)
|
||||
{
|
||||
// Disable jump if vaulting
|
||||
if (VaultComponent->bPressedVault)
|
||||
{
|
||||
bPressedJump = false;
|
||||
}
|
||||
|
||||
// Possibly execute vault
|
||||
if (GetCharacterMovement())
|
||||
{
|
||||
VaultComponent->CheckVaultInput(DeltaTime, GetCharacterMovement()->MovementMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
VaultComponent->CheckVaultInput(DeltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
// Pick up changes in vaulting state to change movement mode
|
||||
// to something other than flying (required for root motion on Z)
|
||||
if (bWasVaulting && !bIsVaulting)
|
||||
{
|
||||
StopVaultAbility();
|
||||
}
|
||||
|
||||
// Call super so we actually jump if we're meant to
|
||||
Super::CheckJumpInput(DeltaTime);
|
||||
|
||||
// Cache end of frame
|
||||
bWasVaulting = bIsVaulting;
|
||||
}
|
||||
|
||||
void AMyVICharacterBase::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
||||
{
|
||||
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||
|
||||
DOREPLIFETIME_CONDITION(AMyVICharacterBase, bRepIsVaulting, COND_SimulatedOnly);
|
||||
DOREPLIFETIME_CONDITION(AMyVICharacterBase, RepMotionMatch, COND_SimulatedOnly);
|
||||
}
|
||||
|
||||
void AMyVICharacterBase::Jump()
|
||||
{
|
||||
// If missing critical components then jump and exit
|
||||
if (!VaultComponent || !GetCharacterMovement())
|
||||
{
|
||||
Super::Jump();
|
||||
return;
|
||||
}
|
||||
|
||||
// Either jump or vault, determined by VaultComponent::EVIJumpKeyPriority
|
||||
if (VaultComponent->Jump(GetCharacterMovement()->GetGravityZ(), CanJump(), GetCharacterMovement()->IsFalling()))
|
||||
{
|
||||
// Jump normally
|
||||
Super::Jump();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Jump key essentially presses the vault input
|
||||
VaultComponent->Vault();
|
||||
}
|
||||
}
|
||||
|
||||
void AMyVICharacterBase::StopJumping()
|
||||
{
|
||||
Super::StopJumping();
|
||||
|
||||
// Release vault input if the jump key pressed vault instead
|
||||
if (VaultComponent)
|
||||
{
|
||||
VaultComponent->StopJumping();
|
||||
}
|
||||
}
|
||||
|
||||
void AMyVICharacterBase::StartVaultAbility_Implementation()
|
||||
{
|
||||
// Called by GA_Vault
|
||||
// Need to be in flying mode to have root motion on Z axis
|
||||
if (GetCharacterMovement() && GetLocalRole() > ROLE_SimulatedProxy)
|
||||
{
|
||||
GetCharacterMovement()->SetMovementMode(MOVE_Flying);
|
||||
}
|
||||
}
|
||||
|
||||
void AMyVICharacterBase::StopVaultAbility()
|
||||
{
|
||||
// Called by CheckJumpInput()
|
||||
// Exiting flying mode
|
||||
// This may put is straight into falling if we aren't properly grounded, which is fine
|
||||
if (GetCharacterMovement() && GetLocalRole() > ROLE_SimulatedProxy)
|
||||
{
|
||||
GetCharacterMovement()->SetMovementMode(GetCharacterMovement()->GetGroundMovementMode());
|
||||
}
|
||||
|
||||
OnStopVaultAbility();
|
||||
}
|
||||
|
||||
void AMyVICharacterBase::OnRep_MotionMatch()
|
||||
{
|
||||
// Simulated proxies update their sync points here, sent from the server during GA_Vault
|
||||
MotionWarpingComponent->AddOrUpdateWarpTargetFromLocationAndRotation(TEXT("VaultSyncPoint"), RepMotionMatch.Location, RepMotionMatch.Direction.Rotation());
|
||||
}
|
||||
|
||||
bool AMyVICharacterBase::IsVaulting() const
|
||||
{
|
||||
// Simulated proxies use the value provided by server
|
||||
if (GetLocalRole() == ROLE_SimulatedProxy)
|
||||
{
|
||||
return bRepIsVaulting;
|
||||
}
|
||||
|
||||
// Local and authority uses gameplay tags for a predicted result
|
||||
if (VaultComponent)
|
||||
{
|
||||
return VaultComponent->IsVaulting();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// *********************************************** //
|
||||
// ******** Begin Pawn Vaulting Interface ******** //
|
||||
// *********************************************** //
|
||||
|
||||
UVIPawnVaultComponent* AMyVICharacterBase::GetPawnVaultComponent_Implementation() const
|
||||
{
|
||||
// You need to override this
|
||||
UVIBlueprintFunctionLibrary::MessageLogError(FString::Printf(TEXT("AVICharacterBase::GetPawnVaultComponent not implemented for { %s }. Cannot Vault."), *GetName()));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UMotionWarpingComponent* AMyVICharacterBase::GetMotionWarpingComponent_Implementation() const
|
||||
{
|
||||
// You need to override this
|
||||
UVIBlueprintFunctionLibrary::MessageLogError(FString::Printf(TEXT("AVICharacterBase::GetMotionWarpingComponent not implemented for { %s }. Cannot Vault."), *GetName()));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FVIAnimSet AMyVICharacterBase::GetVaultAnimSet_Implementation() const
|
||||
{
|
||||
// You need to override this
|
||||
UVIBlueprintFunctionLibrary::MessageLogError(FString::Printf(TEXT("AVICharacterBase::GetVaultAnimSet not implemented for { %s }. Cannot Vault."), *GetName()));
|
||||
return FVIAnimSet();
|
||||
}
|
||||
|
||||
FVITraceSettings AMyVICharacterBase::GetVaultTraceSettings_Implementation() const
|
||||
{
|
||||
// You need to override this
|
||||
UVIBlueprintFunctionLibrary::MessageLogError(FString::Printf(TEXT("AVICharacterBase::GetVaultTraceSettings not implemented for { %s }. Using default trace settings."), *GetName()), false);
|
||||
return FVITraceSettings();
|
||||
}
|
||||
|
||||
FVector AMyVICharacterBase::GetVaultDirection_Implementation() const
|
||||
{
|
||||
// Use input vector if available
|
||||
if (GetCharacterMovement() && !GetCharacterMovement()->GetCurrentAcceleration().IsNearlyZero())
|
||||
{
|
||||
return GetCharacterMovement()->GetCurrentAcceleration();
|
||||
}
|
||||
|
||||
// Use character facing direction if not providing input
|
||||
return GetActorForwardVector();
|
||||
}
|
||||
|
||||
bool AMyVICharacterBase::CanVault_Implementation() const
|
||||
{
|
||||
// Vaulting must finish before starting another vault attempt
|
||||
if (IsVaulting())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Invalid components
|
||||
if (!VaultComponent || !GetCharacterMovement())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Animation instance is required to play vault montage
|
||||
if (!GetMesh() || !GetMesh()->GetAnimInstance())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Authority not initialized (this isn't set on clients)
|
||||
if (HasAuthority() && !VaultComponent->bVaultAbilityInitialized)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Exit if character is in a state they cannot vault from
|
||||
if (GetCharacterMovement()->IsMovingOnGround() || GetCharacterMovement()->IsFalling() || GetCharacterMovement()->IsSwimming())
|
||||
{
|
||||
if (GetCharacterMovement()->IsMovingOnGround() && !VaultComponent->bCanVaultFromGround)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetCharacterMovement()->IsFalling() && !VaultComponent->bCanVaultFromFalling)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetCharacterMovement()->IsSwimming() && !VaultComponent->bCanVaultFromSwimming)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Can't vault while crouching
|
||||
if (!VaultComponent->bCanVaultFromCrouching && GetCharacterMovement()->IsCrouching())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Passed all conditions
|
||||
return true;
|
||||
}
|
||||
|
||||
void AMyVICharacterBase::OnLocalPlayerVault_Implementation(const FVector& Location, const FVector& Direction)
|
||||
{
|
||||
// LocalPlayer just stores the data in the same place for convenience, ease of use, memory reduction, etc
|
||||
RepMotionMatch = FVIRepMotionMatch(Location, Direction);
|
||||
}
|
||||
|
||||
void AMyVICharacterBase::GetVaultLocationAndDirection_Implementation(FVector& OutLocation, FVector& OutDirection) const
|
||||
{
|
||||
// Because LocalPlayer stores in the same place, no need for any testing as they all use RepMotionMatch to store this
|
||||
|
||||
// This is only currently used for FBIK tracing
|
||||
OutLocation = RepMotionMatch.Location;
|
||||
OutDirection = RepMotionMatch.Direction;
|
||||
}
|
||||
|
||||
void AMyVICharacterBase::ReplicateMotionMatch_Implementation(const FVIRepMotionMatch& MotionMatch)
|
||||
{
|
||||
// GA_Vault has directed server to update it's RepMotionMatch property so that it will
|
||||
// be replicated to simulated proxies with 1 decimal point of precision (net quantization)
|
||||
RepMotionMatch = MotionMatch;
|
||||
}
|
||||
|
||||
bool AMyVICharacterBase::IsWalkable_Implementation(const FHitResult& HitResult) const
|
||||
{
|
||||
// Surface we hit can be walked on or not
|
||||
return GetCharacterMovement() && GetCharacterMovement()->IsWalkable(HitResult);
|
||||
}
|
||||
|
||||
bool AMyVICharacterBase::CanAutoVaultInCustomMovementMode_Implementation() const
|
||||
{
|
||||
return true;
|
||||
|
||||
// Example usage commented out
|
||||
|
||||
/*
|
||||
|
||||
if (GetCharacterMovement())
|
||||
{
|
||||
switch (GetCharacterMovement()->CustomMovementMode)
|
||||
{
|
||||
case 0:
|
||||
return false;
|
||||
case 1: // Some example custom mode where auto vault can work
|
||||
return true;
|
||||
case 2:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
// *********************************************** //
|
||||
// ********* End Pawn Vaulting Interface ********* //
|
||||
// *********************************************** //
|
119
EndlessVendetta/Source/EndlessVendetta/MyVICharacterBase.h
Normal file
119
EndlessVendetta/Source/EndlessVendetta/MyVICharacterBase.h
Normal file
@ -0,0 +1,119 @@
|
||||
// Copyright (c) 2019-2022 Drowning Dragons Limited. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "EndlessVendettaCharacter.h"
|
||||
|
||||
#include "VITypes.h"
|
||||
#include "Pawn/VIPawnInterface.h"
|
||||
#include "MyVICharacterBase.generated.h"
|
||||
|
||||
class UMotionWarpingComponent;
|
||||
class UVIPawnVaultComponent;
|
||||
|
||||
/**
|
||||
* An incomplete character base class
|
||||
* Needs to inherit from IAbilitySystemInterface and implement a UVIAbilitySystemComponent
|
||||
* @see: AVICharacterAbilityBase where this is done for you
|
||||
*
|
||||
* Requires multiple overrides which will cause errors if not correctly performed
|
||||
*/
|
||||
UCLASS(abstract)
|
||||
class ENDLESSVENDETTA_API AMyVICharacterBase : public AEndlessVendettaCharacter, public IVIPawnInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
/**
|
||||
* Motion Warping Component used for vaulting
|
||||
*/
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Character)
|
||||
UMotionWarpingComponent* MotionWarpingComponent;
|
||||
|
||||
/**
|
||||
* Pawn Vault Component used for core vaulting logic
|
||||
*
|
||||
* This is added in Blueprint and must be returned via
|
||||
* the IVIPawnInterface::GetPawnVaultComponent function
|
||||
*/
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Character)
|
||||
UVIPawnVaultComponent* VaultComponent;
|
||||
|
||||
protected:
|
||||
/** Simulated proxies use this to update their vaulting state based on server values */
|
||||
UPROPERTY(Replicated, BlueprintReadWrite, Category = Vault)
|
||||
bool bRepIsVaulting;
|
||||
|
||||
/** Used to detect changes in vaulting state and call StopVaultAbility() */
|
||||
UPROPERTY()
|
||||
bool bWasVaulting;
|
||||
|
||||
/**
|
||||
* Simulated proxies use this to reproduce motion matching results provided
|
||||
* by server in the GA_Vault gameplay ability
|
||||
*
|
||||
* Local players use this as a cache for FBIK testing (returned via GetVaultLocationAndDirection)
|
||||
*
|
||||
* Net Serialized to one decimal point of precision
|
||||
*/
|
||||
UPROPERTY(ReplicatedUsing="OnRep_MotionMatch", BlueprintReadWrite, Category = Vault)
|
||||
FVIRepMotionMatch RepMotionMatch;
|
||||
|
||||
public:
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
virtual void CheckJumpInput(float DeltaTime) override;
|
||||
|
||||
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||
|
||||
public:
|
||||
virtual void Jump() override;
|
||||
virtual void StopJumping() override;
|
||||
|
||||
/** Called from gameplay ability when vault stops */
|
||||
UFUNCTION(BlueprintCallable, Category = Vault)
|
||||
void StopVaultAbility();
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = Vault)
|
||||
void OnStopVaultAbility();
|
||||
|
||||
protected:
|
||||
UFUNCTION()
|
||||
void OnRep_MotionMatch();
|
||||
|
||||
public:
|
||||
/**
|
||||
* @return True if vaulting
|
||||
* Correct value must be returned based on net role here
|
||||
* Simulated proxies return bRepIsVaulting
|
||||
* Server & Authority must return CMC bIsVaulting
|
||||
*/
|
||||
UFUNCTION(BlueprintPure, Category = Vault)
|
||||
virtual bool IsVaulting() const;
|
||||
|
||||
// *********************************************** //
|
||||
// *********** Begin IVIPawnInterface ************ //
|
||||
// *********************************************** //
|
||||
|
||||
// Read VIPawnInterface.h for detailed descriptions of these functions or look
|
||||
// inside their functions themselves
|
||||
|
||||
virtual UVIPawnVaultComponent* GetPawnVaultComponent_Implementation() const override;
|
||||
virtual UMotionWarpingComponent* GetMotionWarpingComponent_Implementation() const override;
|
||||
virtual USkeletalMeshComponent* GetMeshForVaultMontage_Implementation() const override { return GetMesh(); }
|
||||
virtual FVIAnimSet GetVaultAnimSet_Implementation() const override;
|
||||
virtual FVITraceSettings GetVaultTraceSettings_Implementation() const override;
|
||||
virtual FVector GetVaultDirection_Implementation() const override;
|
||||
virtual bool CanVault_Implementation() const override;
|
||||
virtual void StartVaultAbility_Implementation() override;
|
||||
virtual void OnLocalPlayerVault_Implementation(const FVector& Location, const FVector& Direction) override;
|
||||
virtual void GetVaultLocationAndDirection_Implementation(FVector& OutLocation, FVector& OutDirection) const override;
|
||||
virtual void ReplicateMotionMatch_Implementation(const FVIRepMotionMatch& MotionMatch) override;
|
||||
virtual bool IsWalkable_Implementation(const FHitResult& HitResult) const override;
|
||||
virtual bool CanAutoVaultInCustomMovementMode_Implementation() const override;
|
||||
|
||||
// *********************************************** //
|
||||
// ************* End IVIPawnInterface ************ //
|
||||
// *********************************************** //
|
||||
};
|
Loading…
Reference in New Issue
Block a user