관리 메뉴

Mini

[UE5] 방마저에따른 데미지 감소 구현 본문

UE5/Advance Damage Techniques

[UE5] 방마저에따른 데미지 감소 구현

Mini_96 2024. 8. 22. 16:22

* execcalc에서 캡쳐속성선언

//BP에노출안할거임, c++안에서만 사용되는 원시구조체
struct AuraDamageStatics
{
    //캡쳐속성 선언 매크로 : 속성포인터가지고있음
   ...

    DECLARE_ATTRIBUTE_CAPTUREDEF(FireResistance);
    DECLARE_ATTRIBUTE_CAPTUREDEF(LightningResistance);
    DECLARE_ATTRIBUTE_CAPTUREDEF(ArcaneResistance);
    DECLARE_ATTRIBUTE_CAPTUREDEF(PhysicalResistance);

* 속성캡쳐 from target(고블린)

AuraDamageStatics()
{
   ..

    DEFINE_ATTRIBUTE_CAPTUREDEF(UAuraAttributeSet, FireResistance, Target, false); //아머라는 속성을 캡쳐하겠다. from 공격자(아우라)임에 주의
    DEFINE_ATTRIBUTE_CAPTUREDEF(UAuraAttributeSet, LightningResistance, Target, false); //아머라는 속성을 캡쳐하겠다. from 공격자(아우라)임에 주의
    DEFINE_ATTRIBUTE_CAPTUREDEF(UAuraAttributeSet, ArcaneResistance, Target, false); //아머라는 속성을 캡쳐하겠다. from 공격자(아우라)임에 주의
    DEFINE_ATTRIBUTE_CAPTUREDEF(UAuraAttributeSet, PhysicalResistance, Target, false); //아머라는 속성을 캡쳐하겠다. from 공격자(아우라)임에 주의

}

* 속성캡쳐 배열에 추가

UExecCalc_Damage::UExecCalc_Damage()
{
   ...

    RelevantAttributesToCapture.Add(DamageStatics().FireResistanceDef); //캡쳐속성 배열에추가
    RelevantAttributesToCapture.Add(DamageStatics().LightningResistanceDef); //캡쳐속성 배열에추가
    RelevantAttributesToCapture.Add(DamageStatics().ArcaneResistanceDef); //캡쳐속성 배열에추가
    RelevantAttributesToCapture.Add(DamageStatics().PhysicalResistanceDef); //캡쳐속성 배열에추가

}

* 태그 : 속성 매칭용 map 만들고 값넣기

    TMap<FGameplayTag,FGameplayEffectAttributeCaptureDefinition> TagsToCaptureDefs; //tag와 속성연결
    
    AuraDamageStatics()
    {
       ...

       const FAuraGameplayTags& Tags = FAuraGameplayTags::Get();
       TagsToCaptureDefs.Add(Tags.Attributes_Secondary_Armor, ArmorDef);
       TagsToCaptureDefs.Add(Tags.Attributes_Secondary_BlockChance, BlockChanceDef);
       TagsToCaptureDefs.Add(Tags.Attributes_Secondary_ArmorPenetration, ArmorPenetrationDef);
       TagsToCaptureDefs.Add(Tags.Attributes_Secondary_CriticalHitChance, CriticalHitChanceDef);
       TagsToCaptureDefs.Add(Tags.Attributes_Secondary_CriticalHitResistance, CriticalHitResistanceDef);
       TagsToCaptureDefs.Add(Tags.Attributes_Secondary_CriticalHitDamage, CriticalHitDamageDef);

       TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Arcane, ArcaneResistanceDef);
       TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Fire, FireResistanceDef);
       TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Lightning, LightningResistanceDef);
       TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Physical, PhysicalResistanceDef);
    }
    
};

 

** 이전강의 누락분

* 데미지태그, 맵<데미지타입 : 저항타입> 추가

struct FAuraGameplayTags
{
public:
   ...

    FGameplayTag Damage;
    FGameplayTag Damage_Fire;
    FGameplayTag Damage_Lightning;
    FGameplayTag Damage_Arcane;
    FGameplayTag Damage_Physical;

    // TArray<FGameplayTag> DamageTypes;
    TMap<FGameplayTag, FGameplayTag> DamageTypesToResistances;

* 게임태그 초기화(데미지타입, 저항타입) && 맵에 추가

/*
 * Damage Types
 */

GameplayTags.Damage_Fire = UGameplayTagsManager::Get().AddNativeGameplayTag(
    FName("Damage.Fire"),
    FString("Fire Damage Type")
    );
GameplayTags.Damage_Lightning = UGameplayTagsManager::Get().AddNativeGameplayTag(
    FName("Damage.Lightning"),
    FString("Lightning Damage Type")
    );
GameplayTags.Damage_Arcane = UGameplayTagsManager::Get().AddNativeGameplayTag(
    FName("Damage.Arcane"),
    FString("Arcane Damage Type")
    );
GameplayTags.Damage_Physical = UGameplayTagsManager::Get().AddNativeGameplayTag(
    FName("Damage.Physical"),
    FString("Physical Damage Type")
    );

/*
 * 방마저 Attributes
 */
GameplayTags.Attributes_Resistance_Arcane = UGameplayTagsManager::Get().AddNativeGameplayTag(
    FName("Attributes.Resistance.Arcane"),
    FString("Arcane Resistance")
    );
GameplayTags.Attributes_Resistance_Fire = UGameplayTagsManager::Get().AddNativeGameplayTag(
    FName("Attributes.Resistance.Fire"),
    FString("Fire Resistance")
    );
GameplayTags.Attributes_Resistance_Lightning = UGameplayTagsManager::Get().AddNativeGameplayTag(
    FName("Attributes.Resistance.Lightning"),
    FString("Lightning Resistance")
    );
GameplayTags.Attributes_Resistance_Physical = UGameplayTagsManager::Get().AddNativeGameplayTag(
    FName("Attributes.Resistance.Physical"),
    FString("Physical Resistance")
    );

/*
 * Map of Damage Types to Resistances
 */
GameplayTags.DamageTypesToResistances.Add(GameplayTags.Damage_Arcane, GameplayTags.Attributes_Resistance_Arcane);
GameplayTags.DamageTypesToResistances.Add(GameplayTags.Damage_Lightning, GameplayTags.Attributes_Resistance_Lightning);
GameplayTags.DamageTypesToResistances.Add(GameplayTags.Damage_Physical, GameplayTags.Attributes_Resistance_Physical);
GameplayTags.DamageTypesToResistances.Add(GameplayTags.Damage_Fire, GameplayTags.Attributes_Resistance_Fire);

 

 

** 이어서

* 저항값을 가져와서 %로 데미지 감소구현

float Damage = 0.f;
for (const TTuple<FGameplayTag, FGameplayTag>& Pair  : FAuraGameplayTags::Get().DamageTypesToResistances)
{
    //map < 데미지타입, 저항속성>
    const FGameplayTag DamageType = Pair.Key;
    const FGameplayTag ResistanceTag = Pair.Value;

    //저항속성이 TagsToCaptureDefs맵에 없는경우 예외처리, 에러시메시지
    checkf(AuraDamageStatics().TagsToCaptureDefs.Contains(ResistanceTag), TEXT("TagsToCaptureDefs doesn`t contain Tag: [%s] in ExceCalc_Damage"),
       *ResistanceTag.ToString());
    //저항태그 에 대항하는 데미지캡쳐
    const FGameplayEffectAttributeCaptureDefinition CaptureDef = AuraDamageStatics().TagsToCaptureDefs[ResistanceTag];

    float DamageTypeValue = Spec.GetSetByCallerMagnitude(DamageType);
    
    float Resistance = 0.f;
    //캡쳐된 속성값 계산
    ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(CaptureDef, EvaluationParameters, Resistance);
    //감소율은 0~100으로 제한
    Resistance = FMath::Clamp(Resistance,0.f,100.f);
    
    DamageTypeValue *= (100.f - Resistance) / 100.f; //저항%만큼 데미지 감소시키기

    Damage += DamageTypeValue;
}

적용전 10의 데미지
enemy base attr > 50% 화염저항 test
적용후 5의 데미지