[박치영] 챕터4 포팅 중 2

pcyoung 2023-08-06 14:03:43 +09:00
parent 1f829698a0
commit 78561c70aa
6 changed files with 132 additions and 57 deletions

View File

@ -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);
IsDisabled = true;
if (CanReceiveHitReaction())
{
StateManagerComponent->SetState(ECharacterState::Disable);
//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;
}

View File

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

View File

@ -34,7 +34,6 @@ void UCombatComponent::ResetAttack()
{
AttackCount = 0;
bIsAttackSaved = false;
bIsAttacking = false;
}
void UCombatComponent::SetMainWeapon(ABaseWeapon* NewWeapon)

View File

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

View File

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

View File

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