[박치영] 전투시스템 작업중

main
PCYPC\pcy35 2023-07-30 21:40:24 +09:00
parent 193c6775eb
commit 2d67e383bb
29 changed files with 289 additions and 33 deletions

View File

@ -4,7 +4,6 @@
#include "Actor/BaseWeapon.h"
#include "Components/CombatComponent.h"
#include "GameFramework/Character.h"
#include "Animation/CombatAnimInstance.h"
ABaseWeapon::ABaseWeapon()
{
@ -30,5 +29,4 @@ void ABaseWeapon::OnEquipped()
UCombatAnimInstance* animInstance = Cast<UCombatAnimInstance>(character->GetMesh()->GetAnimInstance());
animInstance->UpdateCombatType(CombatType);
}
}

View File

@ -5,6 +5,7 @@
#include "CoreMinimal.h"
#include "Actor/BaseEquippable.h"
#include "Enums/CombatType.h"
#include "Animation/CombatAnimInstance.h"
#include "BaseWeapon.generated.h"
/**
@ -26,6 +27,9 @@ public:
public:
FORCEINLINE UAnimMontage* GetEnterCombat() const { return EnterCombat; }
FORCEINLINE UAnimMontage* GetExitCombat() const { return ExitCombat; }
FORCEINLINE TArray<UAnimMontage*>& GetAttackMontage() { return AttackMontage; }
FORCEINLINE TArray<UAnimMontage*>& GetDodgeMontage() { return DodgeMontage; }
protected:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Initialization")
FName HandSocketName;
@ -35,8 +39,12 @@ protected:
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components")
TObjectPtr<class UCombatComponent> CombatComponent;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Animations")
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Montages")
TObjectPtr<UAnimMontage> EnterCombat;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Animations")
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Montages")
TObjectPtr<UAnimMontage> ExitCombat;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Montages")
TArray<TObjectPtr<UAnimMontage>> AttackMontage;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Montages")
TArray<TObjectPtr<UAnimMontage>> DodgeMontage;
};

View File

@ -32,8 +32,8 @@ void APickupActor::Interact(AActor* Caller)
FActorSpawnParameters spawnParam;
spawnParam.Owner = Caller;
spawnParam.Instigator = pawn;
ABaseEquippable* SpawnItem = Cast<ABaseEquippable>(GetWorld()->SpawnActor(Item, &GetActorTransform(),spawnParam));
if(SpawnItem)
ABaseEquippable* SpawnItem = Cast<ABaseEquippable>(GetWorld()->SpawnActor(Item, &GetActorTransform(), spawnParam));
if (SpawnItem)
SpawnItem->OnEquipped();
}
}

View File

@ -10,9 +10,10 @@
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Kismet/KismetMathLibrary.h"
#include "Interface/Interact.h"
#include "Actor/BaseWeapon.h"
#include "Components//CombatComponent.h"
#include "Components/CombatComponent.h"
//////////////////////////////////////////////////////////////////////////
// ACombatCharacter
@ -55,6 +56,10 @@ ACombatCharacter::ACombatCharacter()
// are set in the derived blueprint asset named ThirdPersonCharacter (to avoid direct content references in C++)
CombatComponent = CreateDefaultSubobject<UCombatComponent>(TEXT("CombatComponent"));
CombatEnabled = false;
IsTogglingCombat = false;
IsDodge = false;
}
void ACombatCharacter::BeginPlay()
@ -70,6 +75,45 @@ void ACombatCharacter::BeginPlay()
Subsystem->AddMappingContext(DefaultMappingContext, 0);
}
}
//Player에 무기를 처음부터 들고있게함. 아마도 임시코드
FActorSpawnParameters spawnParam;
spawnParam.Owner = this;
spawnParam.Instigator = this;
ABaseEquippable* SpawnItem = Cast<ABaseEquippable>(GetWorld()->SpawnActor(Weapon, &GetActorTransform(), spawnParam));
if (SpawnItem)
SpawnItem->OnEquipped();
}
void ACombatCharacter::ContinueAttack_Implementation()
{
CombatComponent->SetIsAttacking(false);
if (CombatComponent->GetIsAttackSaved())
{
CombatComponent->SetIsAttackSaved(false);
AttackEvent();
}
}
void ACombatCharacter::ResetAttack_Implementation()
{
CombatComponent->ResetAttack();
}
void ACombatCharacter::ResetCombat_Implementation()
{
CombatComponent->ResetAttack();
IsTogglingCombat = false;
IsDodge = false;
}
FRotator ACombatCharacter::GetDesiredRotation_Implementation()
{
FVector InputVector = GetCharacterMovement()->GetLastInputVector();
if (InputVector.Equals(FVector(0, 0, 0), 0.001f))
return GetActorRotation();
else
return UKismetMathLibrary::MakeRotFromX(GetLastMovementInputVector());
}
//////////////////////////////////////////////////////////////////////////
@ -95,6 +139,12 @@ void ACombatCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerIn
//ToggleCombat
EnhancedInputComponent->BindAction(ToggleCombatAction, ETriggerEvent::Started, this, &ACombatCharacter::ToggleCombat);
//LightAttack
EnhancedInputComponent->BindAction(LightAttackAction, ETriggerEvent::Started, this, &ACombatCharacter::LightAttack);
//Dodge
EnhancedInputComponent->BindAction(DodgeAction, ETriggerEvent::Started, this, &ACombatCharacter::Dodge);
}
}
@ -168,17 +218,110 @@ void ACombatCharacter::ToggleCombat(const FInputActionValue& Value)
{
bool bInput = Value.Get<bool>();
ToggleCombatEvent();
}
void ACombatCharacter::LightAttack(const FInputActionValue& Value)
{
if (CombatComponent->GetIsAttacking())
CombatComponent->SetIsAttackSaved(true);
else
AttackEvent();
}
void ACombatCharacter::Dodge(const FInputActionValue& Value)
{
if (CanPerformDodge())
PerformDodge();
}
void ACombatCharacter::ToggleCombatEvent()
{
ABaseWeapon* baseWeapon = CombatComponent->GetMainWeapon();
if (!baseWeapon)
return;
bool isCombatEnabled = CombatComponent->GetCombatEnabled();
if (!isCombatEnabled)
if (!CanPerformToggleCombat())
return;
if (!CombatComponent->GetCombatEnabled())
PlayAnimMontage(baseWeapon->GetEnterCombat());
else
PlayAnimMontage(baseWeapon->GetExitCombat());
}
void ACombatCharacter::AttackEvent()
{
if (!CanPerformAttack())
return;
if (CombatComponent->GetCombatEnabled())
PerformAttack(CombatComponent->GetAttackCount());
else
ToggleCombatEvent();
}
void ACombatCharacter::PerformAttack(int32 attackIndex)
{
ABaseWeapon* CurrentWeapon = CombatComponent->GetMainWeapon();
if (!CurrentWeapon)
return;
if (!CurrentWeapon->GetAttackMontage().IsValidIndex(attackIndex))
return;
UAnimMontage* attackMontage = CurrentWeapon->GetAttackMontage()[attackIndex];
if(!IsValid(attackMontage))
return;
CombatComponent->SetIsAttacking(true);
PlayAnimMontage(attackMontage);
int idx = attackIndex + 1;
if (idx > CurrentWeapon->GetAttackMontage().Num())
idx = 0;
CombatComponent->SetAttackCount(idx);
}
//인자값은 나중에 필요하면 추가 PerformDodge(int32 dodgeIndex)
void ACombatCharacter::PerformDodge()
{
ABaseWeapon* CurrentWeapon = CombatComponent->GetMainWeapon();
if (!CurrentWeapon)
return;
int32 montageIndex = 0;
TArray<UAnimMontage*> montages = CurrentWeapon->GetDodgeMontage();
if (montages.Num() > montageIndex)
montageIndex = 0;
if (!montages.IsValidIndex(montageIndex))
return;
UAnimMontage* dodgeMontage = CurrentWeapon->GetDodgeMontage()[montageIndex];
if (IsValid(dodgeMontage))
{
IsDodge = true;
PlayAnimMontage(dodgeMontage);
}
else
{
FString str = FString::Printf(TEXT("Dodge Index %n is NOT VALID!!"), montageIndex);
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Blue, str);
}
}
bool ACombatCharacter::CanPerformToggleCombat()
{
return (!CombatComponent->GetIsAttacking() && !IsTogglingCombat);
}
bool ACombatCharacter::CanPerformAttack()
{
return (!CombatComponent->GetIsAttacking() && !IsTogglingCombat);
}
bool ACombatCharacter::CanPerformDodge()
{
return (!CombatComponent->GetIsAttacking() && !IsTogglingCombat && !IsDodge);
}

View File

@ -5,11 +5,12 @@
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "InputActionValue.h"
#include "Interface/CombatInterface.h"
#include "CombatCharacter.generated.h"
UCLASS(config=Game)
class ACombatCharacter : public ACharacter
class ACombatCharacter : public ACharacter, public ICombatInterface
{
GENERATED_BODY()
@ -44,9 +45,40 @@ class ACombatCharacter : public ACharacter
/* ToggleCombat Input Action */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
class UInputAction* ToggleCombatAction;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
class UInputAction* LightAttackAction;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
class UInputAction* DodgeAction;
public:
ACombatCharacter();
public:
/** Returns CameraBoom subobject **/
FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }
/** Returns FollowCamera subobject **/
FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; }
protected:
// APawn interface
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
virtual void BeginPlay();
public:
// Inherited via ICombatInterface
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
void ContinueAttack();
virtual void ContinueAttack_Implementation() override;
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
void ResetAttack();
virtual void ResetAttack_Implementation() override;
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
void ResetCombat();
virtual void ResetCombat_Implementation() override;
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
FRotator GetDesiredRotation();
virtual FRotator GetDesiredRotation_Implementation() override;
protected:
/** Called for movement input */
void Move(const FInputActionValue& Value);
@ -56,21 +88,28 @@ protected:
void Interact(const FInputActionValue& Value);
void ToggleCombat(const FInputActionValue& Value);
protected:
// APawn interface
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
void LightAttack(const FInputActionValue& Value);
void Dodge(const FInputActionValue& Value);
// To add mapping context
virtual void BeginPlay();
public:
/** Returns CameraBoom subobject **/
FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }
/** Returns FollowCamera subobject **/
FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; }
private:
void ToggleCombatEvent();
void AttackEvent();
void PerformAttack(int32 attackIndex);
void PerformDodge();
bool CanPerformToggleCombat();
bool CanPerformAttack();
bool CanPerformDodge();
public:
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta=(AllowPrivateAccess="true"))
TObjectPtr<class UCombatComponent> CombatComponent;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Weapon", meta = (AllowPrivateAccess = "true"))
TSubclassOf<class ABaseEquippable> Weapon;
private:
bool CombatEnabled;
bool IsTogglingCombat;
bool IsDodge;
};

View File

@ -30,9 +30,11 @@ void UCombatComponent::SetCombatEnabled(bool bInputCombat)
}
}
bool UCombatComponent::GetCombatEnabled()
void UCombatComponent::ResetAttack()
{
return bCombatEnabled;
AttackCount = 0;
bIsAttackSaved = false;
bIsAttacking = false;
}
void UCombatComponent::SetMainWeapon(ABaseWeapon* NewWeapon)
@ -45,3 +47,9 @@ void UCombatComponent::SetMainWeapon(ABaseWeapon* NewWeapon)
MainWeapon = NewWeapon;
}
ABaseWeapon* UCombatComponent::GetMainWeapon() const
{
return MainWeapon;
}

View File

@ -21,10 +21,22 @@ public:
UFUNCTION(BlueprintCallable)
void SetCombatEnabled(bool bInputCombat);
UFUNCTION(BlueprintCallable)
bool GetCombatEnabled();
FORCEINLINE bool GetCombatEnabled() { return bCombatEnabled; }
public:
void ResetAttack();
public:
void SetMainWeapon(ABaseWeapon* NewWeapon);
FORCEINLINE ABaseWeapon* GetMainWeapon() const { return MainWeapon; }
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; }
FORCEINLINE void SetAttackCount(int32 count) { AttackCount = count; }
FORCEINLINE int32 GetAttackCount() { return AttackCount; }
private:
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true"))
@ -32,4 +44,13 @@ private:
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true"))
bool bCombatEnabled;
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

@ -0,0 +1,6 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "Interface/CombatInterface.h"
// Add default functionality here for any ICombatInterface functions that are not pure virtual.

View File

@ -0,0 +1,33 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "CombatInterface.generated.h"
// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UCombatInterface : public UInterface
{
GENERATED_BODY()
};
/**
*
*/
class D1_API ICombatInterface
{
GENERATED_BODY()
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
void ContinueAttack();
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
void ResetAttack();
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
void ResetCombat();
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
FRotator GetDesiredRotation();
};