BossFight - 무기 Ability 부여 및 제거

김대겸·2025년 4월 11일

무기 Ability 부여 및 제거

저번에 했던 구현을 통해 무기를 장착하고, 해당 무기에 맞는 InputMapingContext와 AnimLayer을 적용할 수 있게 되었다.

이번에는 각 무기의 공격이나, 특수 능력과 같은 Ability를 추가하고 무기 장착시 플레이어에게 부여 하도록 구현 해보자.

우선 구조체를 작성하여 PlayerWeapon에 추가하자.

🎮 FBFPlayerWeaponData;

USTRUCT(BlueprintType)
struct FBFPlayerWeaponData
{
	GENERATED_BODY()

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (TitleProperty = "InputTag"))
	TArray<FBFAbilitySet>WeaponAbilities;
};

FBFPlayerWeaponData구조체를 작성하여 필요한 정보를 추가해주었다. 앞으로 무기의 기본 공격력이나, 추가적인 Data가 필요하면 해당 구조체에 추가해주면 될듯 하다.

위의 구조체를 PlayerWeapon에 변수로 추가 해주었다.

또한 FGameplayAbilitySpecHandle의 배열을 변수로 추가하여, 등록된Ability를 저장할수 있도록 구현 하였다.

🎮 APlayerWeapon.h

UCLASS()
class BOSSFIGHT_API APlayerWeapon : public AWeaponBase
{
	GENERATED_BODY()

public:
	void AssignGrantAbilitySpecHandles(const TArray<FGameplayAbilitySpecHandle>& InSpecHandles);

	TArray<FGameplayAbilitySpecHandle>GetGrantAbilitySpecHandle() const;

	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	FBFPlayerWeaponData WeaponData;

private:
	TArray<FGameplayAbilitySpecHandle>GrantAbilitySpecHandles;
};

🎮 APlayerWeapon.cpp

void APlayerWeapon::AssignGrantAbilitySpecHandles(const TArray<FGameplayAbilitySpecHandle>& InSpecHandles)
{
	GrantAbilitySpecHandles = InSpecHandles;
}

TArray<FGameplayAbilitySpecHandle> APlayerWeapon::GetGrantAbilitySpecHandle() const
{
	return GrantAbilitySpecHandles;
}

AssignGrantAbilitySpecHandles()함수를 통해 부여된 Ability를 저장하고 GetGrantAbilitySpecHandle()를 통해 저장된 배열을 반환 하도록 함수를 작성 하였다.

다음으로 BFAbilitySystemComponent에서 Ability를 등록 및 제거하는기능을 구현 해주자.

🎮 UBFAbilitySystemComponent.cpp

void UBFAbilitySystemComponent::GrantPlayerWeaponAbilities(const TArray<FBFAbilitySet>& PlayerWeaponAbilities, TArray<FGameplayAbilitySpecHandle>& OutGrantAbilitySpecHandles, int32 ApplyLevel)
{
	if (PlayerWeaponAbilities.IsEmpty()) { return; }
	for (const FBFAbilitySet& AbilitySet : PlayerWeaponAbilities)
	{
		if (!AbilitySet.IsVaild()) continue;

		FGameplayAbilitySpec AbilitySpec(AbilitySet.AbilityToGrant);
		AbilitySpec.SourceObject = GetAvatarActor();
		AbilitySpec.Level = ApplyLevel;
		AbilitySpec.DynamicAbilityTags.AddTag(AbilitySet.InputTag);

		OutGrantAbilitySpecHandles.AddUnique(GiveAbility(AbilitySpec));
	}
}

void UBFAbilitySystemComponent::RemoveGrantPlayerWeaponAbilities(TArray<FGameplayAbilitySpecHandle>& InSpecHandleToRemove)
{
	if (InSpecHandleToRemove.IsEmpty()) return;

	for (FGameplayAbilitySpecHandle& SpecHandle : InSpecHandleToRemove)
	{
		if (SpecHandle.IsValid())
		{
			ClearAbility(SpecHandle);
		}
	}
	InSpecHandleToRemove.Empty();
}

GrantPlayerWeaponAbilities() 함수로 Ability를 부여 해주고 OutGrantAbilitySpecHandles에 추가하여Out매개변수로 내보내주고 있다.

RemoveGrantPlayerWeaponAbilities() 함수에서는 AbilitySpceHandle를 통해 SpecHandle이 유효하면 제거해주도록 기능을 구현 하였다.

마지막으로 PlayerEquipmentComponent RegisterWeapon()함수를 수정 해주었다.

기존의 PawnEquipmentComponent RegisterWeapon()함수의 내부를 지우고, PlayerEquipmentComponent에서 RegisterWeapon()를 Override하도록 하였다.

🎮 UPlayerEquipmentComponent.cpp

void UPlayerEquipmentComponent::RegisterWeapon(TArray<AWeaponBase*> NewWeapon)
{
	ABFPlayerCharacter* Owner = Cast<ABFPlayerCharacter>(GetOwner());
	UBFAbilitySystemComponent* ASC = Owner->GetBFAbilitySystemComponent();
	if (!CurrentWeaponMap.IsEmpty())
	{
		for (TPair Pair : CurrentWeaponMap)
		{
        	// 저장된 AbilitySpecHanlde을 통해 부여되어 있던 Ability 제거
			APlayerWeapon* PlayerWeapon = Cast<APlayerWeapon>(Pair.Value);
			TArray<FGameplayAbilitySpecHandle> SpecHandles = PlayerWeapon->GetGrantAbilitySpecHandle();
			ASC->RemoveGrantPlayerWeaponAbilities(SpecHandles);

			Pair.Value->Destroy();
		}
		CurrentWeaponMap.Empty();
	}
	for (AWeaponBase* Weapon : NewWeapon)
	{
		CurrentWeaponMap.Add(Weapon->GetWeaponType(), Weapon);

		// Ability부여 및 부여된 Ability의 SpecHandle을 저장
		APlayerWeapon* PlayerWeapon = Cast<APlayerWeapon>(Weapon);
		TArray<FGameplayAbilitySpecHandle> SpecHandles;
		ASC->GrantPlayerWeaponAbilities(PlayerWeapon->WeaponData.WeaponAbilities, SpecHandles);
		PlayerWeapon->AssignGrantAbilitySpecHandles(SpecHandles);
	}

	UBFFunctionLibrary::AddGameplayTagToActorIfNone(GetOwner(), BFGameplayTag::Player_WeaponEquip);
}

위와 같이 RegisterWeapon()함수를 수정 해주었다.

작동 영상

위와같이 무기를 장착할때마다 Ability가 부여 및 제거되는것을 확인 하였다.

다음에는 실제 무기 공격을 구현 해보겠다.

0개의 댓글