[박치영] 충돌 및 상태패턴 변경
parent
add1abe08a
commit
79cfdb003a
|
@ -57,15 +57,16 @@ ACombatCharacter::ACombatCharacter()
|
|||
// Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character)
|
||||
// are set in the derived blueprint asset named ThirdPersonCharacter (to avoid direct content references in C++)
|
||||
|
||||
|
||||
// Setting CombatComponent
|
||||
CombatComponent = CreateDefaultSubobject<UCombatComponent>(TEXT("CombatComponent"));
|
||||
|
||||
CombatEnabled = false;
|
||||
IsTogglingCombat = false;
|
||||
IsDodge = false;
|
||||
IsDisabled = false;
|
||||
IsDead = false;
|
||||
Health = 100.f;
|
||||
// Setting StateManagerComponent
|
||||
StateManagerComponent = CreateDefaultSubobject<UStateManagerComponent>(TEXT("StateManagerComponent"));
|
||||
StateManagerComponent->OnStateBegin.AddUObject(this, &ACombatCharacter::CharacterStateBegin);
|
||||
StateManagerComponent->OnStateEnd.AddUObject(this, &ACombatCharacter::CharacterStateEnd);
|
||||
|
||||
Health = 100.f;
|
||||
PelvisBoneName = TEXT("pelvis");
|
||||
}
|
||||
|
||||
|
@ -108,20 +109,24 @@ float ACombatCharacter::TakeDamage(float Damage, FDamageEvent const& DamageEvent
|
|||
//Hit Effect
|
||||
UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), HitEmitter, PointDamageEvent->HitInfo.Location);
|
||||
|
||||
//Play Animation
|
||||
PlayAnimMontage(HitMontage);
|
||||
if (CanReceiveHitReaction())
|
||||
{
|
||||
StateManagerComponent->SetState(ECharacterState::Disable);
|
||||
|
||||
IsDisabled = true;
|
||||
//Play Animation
|
||||
PlayAnimMontage(HitMontage);
|
||||
}
|
||||
}
|
||||
return fDamage;
|
||||
}
|
||||
|
||||
void ACombatCharacter::ContinueAttack_Implementation()
|
||||
{
|
||||
CombatComponent->SetIsAttacking(false);
|
||||
if (CombatComponent->GetIsAttackSaved())
|
||||
{
|
||||
CombatComponent->SetIsAttackSaved(false);
|
||||
if (StateManagerComponent->GetCurrentState() == ECharacterState::Attacking)
|
||||
StateManagerComponent->SetState(ECharacterState::Nothing);
|
||||
AttackEvent();
|
||||
}
|
||||
}
|
||||
|
@ -134,8 +139,8 @@ void ACombatCharacter::ResetAttack_Implementation()
|
|||
void ACombatCharacter::ResetCombat_Implementation()
|
||||
{
|
||||
CombatComponent->ResetAttack();
|
||||
IsTogglingCombat = false;
|
||||
IsDodge = false;
|
||||
StateManagerComponent->ResetState();
|
||||
StateManagerComponent->SetState(ECharacterState::Nothing);
|
||||
}
|
||||
|
||||
FRotator ACombatCharacter::GetDesiredRotation_Implementation()
|
||||
|
@ -149,7 +154,9 @@ FRotator ACombatCharacter::GetDesiredRotation_Implementation()
|
|||
|
||||
bool ACombatCharacter::CanReceiveDamage_Implementation()
|
||||
{
|
||||
return !IsDead;
|
||||
bool result;
|
||||
result = (StateManagerComponent->GetCurrentState() != ECharacterState::Dead);
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -158,7 +165,8 @@ bool ACombatCharacter::CanReceiveDamage_Implementation()
|
|||
void ACombatCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
|
||||
{
|
||||
// Set up action bindings
|
||||
if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent)) {
|
||||
if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
|
||||
{
|
||||
|
||||
//Jumping
|
||||
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ACharacter::Jump);
|
||||
|
@ -247,7 +255,7 @@ void ACombatCharacter::ToggleCombat(const FInputActionValue& Value)
|
|||
|
||||
void ACombatCharacter::LightAttack(const FInputActionValue& Value)
|
||||
{
|
||||
if (CombatComponent->GetIsAttacking())
|
||||
if (StateManagerComponent->GetCurrentState() == ECharacterState::Attacking)
|
||||
CombatComponent->SetIsAttackSaved(true);
|
||||
else
|
||||
AttackEvent();
|
||||
|
@ -259,6 +267,49 @@ void ACombatCharacter::Dodge(const FInputActionValue& Value)
|
|||
PerformDodge();
|
||||
}
|
||||
|
||||
void ACombatCharacter::CharacterStateBegin(ECharacterState CharState)
|
||||
{
|
||||
switch (CharState)
|
||||
{
|
||||
case ECharacterState::Nothing:
|
||||
break;
|
||||
case ECharacterState::Attacking:
|
||||
break;
|
||||
case ECharacterState::Dodging:
|
||||
break;
|
||||
case ECharacterState::GeneralActionState:
|
||||
break;
|
||||
case ECharacterState::Dead:
|
||||
PerformDeath();
|
||||
break;
|
||||
case ECharacterState::Disable:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ACombatCharacter::CharacterStateEnd(ECharacterState CharState)
|
||||
{
|
||||
switch (CharState)
|
||||
{
|
||||
case ECharacterState::Nothing:
|
||||
break;
|
||||
case ECharacterState::Attacking:
|
||||
break;
|
||||
case ECharacterState::Dodging:
|
||||
break;
|
||||
case ECharacterState::GeneralActionState:
|
||||
break;
|
||||
case ECharacterState::Dead:
|
||||
break;
|
||||
case ECharacterState::Disable:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ACombatCharacter::ToggleCombatEvent()
|
||||
{
|
||||
ABaseWeapon* baseWeapon = CombatComponent->GetMainWeapon();
|
||||
|
@ -291,7 +342,7 @@ void ACombatCharacter::CharacterTakeDamage(float InDamage)
|
|||
Health = UKismetMathLibrary::Clamp(tmp, 0, Health);
|
||||
|
||||
if (Health <= 0)
|
||||
PerformDeath();
|
||||
StateManagerComponent->SetState(ECharacterState::Dead);
|
||||
}
|
||||
|
||||
void ACombatCharacter::ApplyHitReactionPhysicsVelocity(float InitialSpeed)
|
||||
|
@ -326,7 +377,7 @@ void ACombatCharacter::PerformAttack(int32 attackIndex)
|
|||
if(!IsValid(attackMontage))
|
||||
return;
|
||||
|
||||
CombatComponent->SetIsAttacking(true);
|
||||
StateManagerComponent->SetState(ECharacterState::Attacking);
|
||||
PlayAnimMontage(attackMontage);
|
||||
|
||||
int idx = attackIndex + 1;
|
||||
|
@ -352,7 +403,7 @@ void ACombatCharacter::PerformDodge()
|
|||
UAnimMontage* dodgeMontage = CurrentWeapon->GetDodgeMontage()[montageIndex];
|
||||
if (IsValid(dodgeMontage))
|
||||
{
|
||||
IsDodge = true;
|
||||
StateManagerComponent->SetState(ECharacterState::Dodging);
|
||||
PlayAnimMontage(dodgeMontage);
|
||||
}
|
||||
else
|
||||
|
@ -364,7 +415,6 @@ void ACombatCharacter::PerformDodge()
|
|||
|
||||
void ACombatCharacter::PerformDeath()
|
||||
{
|
||||
IsDead = true;
|
||||
EnableRagdoll();
|
||||
ApplyHitReactionPhysicsVelocity(2000.f); //충돌을 좀 더 그럴싸하게 하기 위해서 뒷방향으로 충격
|
||||
|
||||
|
@ -383,11 +433,15 @@ void ACombatCharacter::PerformDeath()
|
|||
bool ACombatCharacter::CanPerformToggleCombat()
|
||||
{
|
||||
bool ReturnValue = true;
|
||||
ReturnValue &= !CombatComponent->GetIsAttacking();
|
||||
ReturnValue &= !IsTogglingCombat;
|
||||
ReturnValue &= !IsDodge;
|
||||
ReturnValue &= !IsDisabled;
|
||||
ReturnValue &= !IsDead;
|
||||
|
||||
TArray<ECharacterState> inputArr = {
|
||||
ECharacterState::Attacking,
|
||||
ECharacterState::Dodging,
|
||||
ECharacterState::Dead,
|
||||
ECharacterState::Disable,
|
||||
ECharacterState::GeneralActionState
|
||||
};
|
||||
ReturnValue &= !StateManagerComponent->IsCurrentStateEqualToAny(inputArr);
|
||||
ReturnValue &= !GetCharacterMovement()->IsFalling();
|
||||
return ReturnValue;
|
||||
}
|
||||
|
@ -395,23 +449,27 @@ bool ACombatCharacter::CanPerformToggleCombat()
|
|||
bool ACombatCharacter::CanPerformAttack()
|
||||
{
|
||||
bool ReturnValue = true;
|
||||
ReturnValue &= !CombatComponent->GetIsAttacking();
|
||||
ReturnValue &= !IsTogglingCombat;
|
||||
ReturnValue &= !IsDodge;
|
||||
ReturnValue &= !IsDisabled;
|
||||
ReturnValue &= !IsDead;
|
||||
ReturnValue &= !GetCharacterMovement()->IsFalling();
|
||||
TArray<ECharacterState> inputArr = {
|
||||
ECharacterState::Attacking,
|
||||
ECharacterState::Dodging,
|
||||
ECharacterState::Dead,
|
||||
ECharacterState::Disable,
|
||||
ECharacterState::GeneralActionState
|
||||
};
|
||||
ReturnValue &= !StateManagerComponent->IsCurrentStateEqualToAny(inputArr);
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
bool ACombatCharacter::CanPerformDodge()
|
||||
{
|
||||
bool ReturnValue = true;
|
||||
ReturnValue &= !CombatComponent->GetIsAttacking();
|
||||
ReturnValue &= !IsTogglingCombat;
|
||||
ReturnValue &= !IsDodge;
|
||||
ReturnValue &= !IsDisabled;
|
||||
ReturnValue &= !IsDead;
|
||||
TArray<ECharacterState> inputArr = {
|
||||
ECharacterState::Dodging,
|
||||
ECharacterState::Dead,
|
||||
ECharacterState::Disable,
|
||||
ECharacterState::GeneralActionState
|
||||
};
|
||||
ReturnValue &= !StateManagerComponent->IsCurrentStateEqualToAny(inputArr);
|
||||
ReturnValue &= !GetCharacterMovement()->IsFalling();
|
||||
return ReturnValue;
|
||||
}
|
||||
|
@ -419,14 +477,26 @@ bool ACombatCharacter::CanPerformDodge()
|
|||
bool ACombatCharacter::CanJumping()
|
||||
{
|
||||
bool ReturnValue = true;
|
||||
ReturnValue &= !CombatComponent->GetIsAttacking();
|
||||
ReturnValue &= !IsTogglingCombat;
|
||||
ReturnValue &= !IsDodge;
|
||||
ReturnValue &= !IsDisabled;
|
||||
ReturnValue &= !IsDead;
|
||||
TArray<ECharacterState> inputArr = {
|
||||
ECharacterState::Dodging,
|
||||
ECharacterState::Dead,
|
||||
ECharacterState::Disable,
|
||||
ECharacterState::GeneralActionState
|
||||
};
|
||||
ReturnValue &= !StateManagerComponent->IsCurrentStateEqualToAny(inputArr);
|
||||
ReturnValue &= !GetCharacterMovement()->IsFalling();
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
bool ACombatCharacter::CanReceiveHitReaction()
|
||||
{
|
||||
bool ReturnValue = true;
|
||||
TArray<ECharacterState> inputArr = {
|
||||
ECharacterState::Dead,
|
||||
};
|
||||
ReturnValue &= !StateManagerComponent->IsCurrentStateEqualToAny(inputArr);
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "GameFramework/Character.h"
|
||||
#include "InputActionValue.h"
|
||||
#include "Interface/CombatInterface.h"
|
||||
#include "Components/StateManagerComponent.h"
|
||||
#include "CombatCharacter.generated.h"
|
||||
|
||||
|
||||
|
@ -93,6 +94,10 @@ protected:
|
|||
void LightAttack(const FInputActionValue& Value);
|
||||
void Dodge(const FInputActionValue& Value);
|
||||
|
||||
private:
|
||||
void CharacterStateBegin(ECharacterState CharState);
|
||||
void CharacterStateEnd(ECharacterState CharState);
|
||||
|
||||
private:
|
||||
void ToggleCombatEvent();
|
||||
void AttackEvent();
|
||||
|
@ -102,6 +107,7 @@ private:
|
|||
|
||||
void PerformAttack(int32 attackIndex);
|
||||
void PerformDodge();
|
||||
|
||||
UFUNCTION(BlueprintCallable) //ÀÓ½Ã
|
||||
void PerformDeath();
|
||||
|
||||
|
@ -109,10 +115,14 @@ private:
|
|||
bool CanPerformAttack();
|
||||
bool CanPerformDodge();
|
||||
bool CanJumping();
|
||||
bool CanReceiveHitReaction();
|
||||
public:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta=(AllowPrivateAccess="true"))
|
||||
TObjectPtr<class UCombatComponent> CombatComponent;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta=(AllowPrivateAccess="true"))
|
||||
TObjectPtr<class UStateManagerComponent> StateManagerComponent;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Weapon", meta = (AllowPrivateAccess = "true"))
|
||||
TSubclassOf<class ABaseEquippable> Weapon;
|
||||
|
||||
|
@ -130,12 +140,5 @@ public:
|
|||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats", meta = (AllowPrivateAccess = "true"))
|
||||
float Health;
|
||||
private:
|
||||
bool CombatEnabled;
|
||||
bool IsTogglingCombat;
|
||||
bool IsDodge;
|
||||
bool IsDisabled;
|
||||
bool IsDead;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ void UCombatComponent::ResetAttack()
|
|||
{
|
||||
AttackCount = 0;
|
||||
bIsAttackSaved = false;
|
||||
bIsAttacking = false;
|
||||
}
|
||||
|
||||
void UCombatComponent::SetMainWeapon(ABaseWeapon* NewWeapon)
|
||||
|
|
|
@ -29,9 +29,6 @@ public:
|
|||
void SetMainWeapon(ABaseWeapon* NewWeapon);
|
||||
FORCEINLINE ABaseWeapon* GetMainWeapon() const;
|
||||
|
||||
FORCEINLINE void SetIsAttacking(bool attacking) { bIsAttacking = attacking; }
|
||||
FORCEINLINE bool GetIsAttacking() const { return bIsAttacking; }
|
||||
|
||||
FORCEINLINE void SetIsAttackSaved(bool attackSaved) { bIsAttackSaved = attackSaved; }
|
||||
FORCEINLINE bool GetIsAttackSaved() const { return bIsAttackSaved; }
|
||||
|
||||
|
@ -48,9 +45,6 @@ private:
|
|||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true"))
|
||||
bool bIsAttackSaved;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true"))
|
||||
bool bIsAttacking;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true"))
|
||||
int32 AttackCount;
|
||||
};
|
||||
|
|
|
@ -36,9 +36,9 @@ void UStateManagerComponent::SetState(ECharacterState NewState)
|
|||
{
|
||||
if (NewState != CurrentState)
|
||||
{
|
||||
//TODO : Delegate 함수 호출 (Call on State End)
|
||||
OnStateEnd.Broadcast(CurrentState);
|
||||
CurrentState = NewState;
|
||||
//TODO : Delegate 함수 호출 (Call on State Begin)
|
||||
OnStateBegin.Broadcast(CurrentState);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,9 @@ enum class ECharacterState : uint8
|
|||
Disable UMETA(DisplayName = "Disable")
|
||||
};
|
||||
|
||||
DECLARE_MULTICAST_DELEGATE_OneParam(FStateBegin, ECharacterState);
|
||||
DECLARE_MULTICAST_DELEGATE_OneParam(FStateEnd, ECharacterState);
|
||||
|
||||
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
|
||||
class D1_API UStateManagerComponent : public UActorComponent
|
||||
{
|
||||
|
@ -39,6 +42,12 @@ public:
|
|||
ECharacterState GetCurrentState();
|
||||
void ResetState();
|
||||
bool IsCurrentStateEqualToAny(TArray<ECharacterState> StatesToCheck);
|
||||
|
||||
public: //Delegate
|
||||
FStateBegin OnStateBegin;
|
||||
FStateEnd OnStateEnd;
|
||||
|
||||
private:
|
||||
ECharacterState CurrentState;
|
||||
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue