버스트 스킬 시스템 구현 계획
책임 분리
GA_Burst (얇음)
└─ 매칭 / 슬롯 소비 / 몽타주 재생 / 컴포넌트에 신호
PlayerCombatComponent (적중 감지 허브)
└─ 노티파이 수신 / AttackType 분기 / 트레이스·오버랩 / GE 인플릭트
월드/투사체 액터 BP (자기 콜리전 책임)
└─ 자기 overlap 감지 → PlayerCombatComponent에 적중 보고
| 책임 | 담당 |
|---|---|
| ElementPattern 매칭 | GA_Burst::FindMatchingCombination |
| 게이지 슬롯 소비 | GA_Burst → ElementGaugeComponent |
| 몽타주 재생 | GA_Burst::PlayMontageAndWait |
| AttackType 분기 | PlayerCombatComponent::OnBurstHit |
| Cleave/Dash/AoE 트레이스 | PlayerCombatComponent |
| Projectile 적중 | BP_Projectile_* 액터 자체 콜리전 |
| GroundEruption 적중 | BP_* 월드 액터 자체 콜리전 |
| 데미지/상태 GE 인플릭트 | PlayerCombatComponent::ApplyHitToTarget |
| 원소 반응 | 별도 시스템 (Step 7) |
Step 1 — FSkillCombination 확장
목표: 명세 10개 스킬을 데이터 한 행으로 표현 가능하게 만든다.
산출물:
Source/Retrieve/Data/RetrieveDataTableTypes.hEBurstAttackTypeenumEBurstHitSourceenumFBurstHitInstancestructFSkillCombination재구성
작업:
- 기존 7개 필드 중
PrimaryEffect,SecondaryEffect,DamageMultiplier,EffectDuration제거 - enum 2종 +
FBurstHitInstance신규 추가 FSkillCombination에 메타/공격형태/HitSequence/연출 섹션으로 재정렬- forward declaration 추가 (
UNiagaraSystem,USoundBase)
완료 조건:
- 컴파일 성공
- 에디터에서
DT_SkillCombination행 추가 시 모든 필드 노출 EditCondition이 AttackType에 따라 부속 필드 가시성 제어
검증: FFF 한 행을 입력해서 ElementPattern={Fire:3}으로 매칭되는지 기존 FindMatchingCombination 호출
Step 2 — AnimNotify_BurstHit 신설
목표: 몽타주 노티파이가 HitSequence[HitIndex]를 발동시키는 컨벤션 확립.
산출물:
Source/Retrieve/Animation/AnimNotify_BurstHit.h/.cpp
작업:
UCLASS(DisplayName = "Burst Hit")
class UAnimNotify_BurstHit : public UAnimNotify
{
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Burst")
int32 HitIndex = 0;
virtual void Notify(USkeletalMeshComponent* MeshComp, ...) override;
};
Notify 안에서:
- Owner Actor 검증
PlayerCombatComponent가져오기Combat->OnBurstHit(HitIndex)호출
완료 조건:
- 컴파일 성공
- 임의 몽타주에 노티파이 박고 UE_LOG로 발동 확인
검증: 몽타주 트랙에 BurstHit(0), BurstHit(1) 두 개 박고 로그 두 번 찍히는지
Step 3 — PlayerCombatComponent 뼈대
목표: 적중 감지 허브의 외형만 먼저 만들어둔다 (분기 로직은 Step 5).
산출물:
Source/Retrieve/Components/PlayerCombatComponent.h/.cpp
작업:
class UPlayerCombatComponent : public UActorComponent
{
// 현재 진행 중인 스킬 컨텍스트
UPROPERTY()
const FSkillCombination* ActiveSkill = nullptr;
UFUNCTION(BlueprintCallable)
void BeginBurstSkill(const FSkillCombination* Row);
UFUNCTION(BlueprintCallable)
void EndBurstSkill();
UFUNCTION(BlueprintCallable)
void OnBurstHit(int32 HitIndex);
private:
// AttackType별 분기 (Step 5에서 채움)
void DoCleaveHit(const FBurstHitInstance& Hit);
void DoProjectileHit(const FBurstHitInstance& Hit);
void DoGroundEruptionHit(const FBurstHitInstance& Hit);
void DoDashHit(const FBurstHitInstance& Hit);
void DoAoEHit(const FBurstHitInstance& Hit);
// 공통 인플릭트
void ApplyHitToTarget(AActor* Target, const FBurstHitInstance& Hit);
// GroundEruption 전용
TWeakObjectPtr<AActor> SpawnedWorldActor;
};
완료 조건:
- 컴파일 성공
- 플레이어 캐릭터 BP에 컴포넌트 추가 가능
OnBurstHit호출 시 UE_LOG로 HitIndex/AttackType 출력
검증: Step 2의 노티파이가 컴포넌트에 도달하는지 로그 확인
Step 4 — GA_Burst 리팩토링
목표: GA는 매칭/슬롯/몽타주/컴포넌트 위임까지만 책임.
작업:
GA_Burst.cpp::ActivateAbility안의 주석(미구현)부분을 다음으로 교체:Avatar->FindComponentByClass<UPlayerCombatComponent>()검증Combat->BeginBurstSkill(MatchedRow)호출PlayMontageAndWait어빌리티 태스크로MatchedRow->AttackMontage재생OnBlendOut/OnCompleted/OnInterrupted콜백에Combat->EndBurstSkill+EndAbility연결
완료 조건:
- 게이지 3스택 → 버스트 발동 → 몽타주 재생 → 정상 종료
검증: FFF 게이지 채우고 버스트 키 입력 → 몽타주 끝까지 재생 + 로그 정상
Step 5 — AttackType별 분기 구현
각 sub-step은 하나의 PR 단위. FFF 부터 시작해서 가장 단순한 케이스로 검증한 뒤 복잡한 것으로 진행.
Step 5-1. Cleave (FFF, FFW)
작업:
PlayerCombatComponent에ActiveHitboxComp : USphereComponent멤버 추가 (적과 대칭)DoCleaveHit구현:HitSource에 따라 attach 본 결정 (Sword → Weapon_R 소켓 / Shield → 방패 소켓 / Body → root)- SphereOverlap으로 적 검출
- 적마다
ApplyHitToTarget호출
ApplyHitToTarget구현:DamageEffect에 SetByCaller로Data.Damage = AttackPower * Hit.DamageMultiplier전달Hit.StatusEffects순회하며 ApplyGameplayEffectToTarget
검증: FFF로 적 한 마리 죽이기 / FFW로 1타 화상 + 2타 추위 부여 확인
Step 5-2. AreaOfEffect (FWA)
작업:
DoAoEHit구현:- 캐릭터 위치 기준
AoeRadius구체 오버랩 - 적마다
ApplyHitToTarget호출 (StatusEffects = [GE_Vulnerable])
- 캐릭터 위치 기준
검증: FWA로 주변 적 다수에게 취약 부여
Step 5-3. Dash (AAF, AAW)
작업:
BeginBurstSkill에서 AttackType=Dash면 캐릭터 전방DashDistance만큼 LaunchCharacter- 돌진 중 캡슐 overlap 리스닝 (
OnComponentBeginOverlap바인딩) - 처음 닿은 적에게
ApplyHitToTarget(중복 방지)
검증: AAF로 전방 돌진 + 적 적중 시 화상 / AAW 동일하게 추위
Step 5-4. Projectile (AAA, FFA, WWA)
작업:
- 액터 BP 3종 생성:
BP_Projectile_SwordSlash(AAA용)BP_Projectile_FireSlash(FFA용)BP_Projectile_WaterSlash(WWA용)
- 액터 공통 인터페이스:
void Initialize(const FBurstHitInstance& HitData, AActor* InInstigator); - 액터의
OnComponentBeginOverlap:InInstigator의PlayerCombatComponent->ApplyHitToTarget(OverlappedActor, HitData)
DoProjectileHit구현:MatchedRow->ProjectileClass액터 스폰Initialize호출하며 HitData 전달- 캐릭터 전방으로 발사
검증: AAA로 검기 3발 발사 + 적 적중 시 데미지 / FFA로 화상 적용 / WWA로 추위 적용
Step 5-5. GroundEruption (WWW, WWF)
작업:
- 액터 BP 2종 생성:
BP_WaterPillar(WWW용, 일정 시간 지속)BP_HotWater(WWF용)
- 액터는 자기 콜리전 + Niagara + 자체 LifeTime (self-destroy) 보유
DoGroundEruptionHit구현:- HitIndex=0일 때:
WorldSpawnActorClass를 캐릭터 전방WorldSpawnDistance에 스폰 →SpawnedWorldActor저장 - HitIndex>0일 때:
SpawnedWorldActor의 overlap 영역 내 적에게ApplyHitToTarget
- HitIndex=0일 때:
EndBurstSkill에서SpawnedWorldActor참조 해제 (액터는 자체 LifeTime으로 사라짐)
검증:
- WWW 발동 → 물기둥 1개 솟음 → 안에 있는 적이 5회 데미지 + 추위 지속시간 갱신
- WWF 발동 → 열탕 솟음 → 1회 데미지 + 추위→화상 순차 부여 → 반응 트리거(Step 7 이후)
Step 6 — 상태 GE 작성
목표: 화상/추위/취약 GE를 통일된 정책으로 만든다.
산출물:
GE_StatusBase(BP, 부모)GE_Burn(BP)GE_Cold(BP)GE_Vulnerable(BP)GE_BurstDamage(BP, SetByCallerData.Damage)
GE_StatusBase 정책 (모든 상태 GE 공통):
Duration Policy : Has Duration (5.0s)
Stacking Type : Aggregate by Target
Stacking Limit Count : 1
Stacking Duration Refresh Policy : Refresh on Successful Application
Stacking Period Reset Policy : Reset on Successful Application
각 GE 별 효과:
GE_Burn: 0.5초 주기 고정 피해 (Modifier on Period)GE_Cold:MoveSpeedMultiplier × 0.8(Infinite-style Modifier)GE_Vulnerable:IncomingDamageMultiplier × 1.15
완료 조건:
- 적 캐릭터에 GE 적용 시 5초 동안 효과 발동
- 재적용 시 스택 없이 지속시간만 갱신
검증: 디버그 명령으로 적에게 GE_Burn 두 번 적용 → 스택 1 유지 + 두 번째 적용 시점부터 5초 다시 카운트
Step 7 — 원소 반응 시스템
목표: 화상↔추위 두 반응을 데이터 + 코드로 구현.
산출물:
Source/Retrieve/Data/RetrieveDataTableTypes.h에FElementReactionRow추가DT_ElementReaction데이터 테이블UElementReactionComponent또는 ASC 이벤트 리스너 로직
반응 정의:
| 기존 상태 | 들어온 상태 | 결과 |
|---|---|---|
| Burn | Cold | 추가 데미지 발동 + Burn 제거 |
| Cold | Burn | 이동속도 -40% 5초 + Cold 제거 |
구현 패턴:
- ASC의
OnGameplayEffectAppliedToTarget또는OnActiveGameplayEffectAdded리스너 - 적용된 GE의 태그가 Status.X일 때, 대상이 이미 Status.Y를 가지고 있으면 매칭되는 반응 행 찾기
- 매칭되면
ReactionEffect적용 +StatusesToRemove제거
완료 조건:
- WWF로 추위→화상 부여 시 자동으로 이동속도 추가 감속
- FFW의 1타 화상→2타 추위 부여 시 추가 데미지
작업 외 약속 (팀룰 / 컨벤션)
데이터 영역 외에서 잡혀야 할 약속들:
- Status GE 정책 —
GE_StatusBase상속 강제 - World 액터 BP 규약 — 콜리전 + VFX + 자체 LifeTime (self-destroy)
- 노티파이 컨벤션 —
AnimNotify_BurstHit(HitIndex)로HitSequence[i]발동 - Projectile 인터페이스 —
Initialize(FBurstHitInstance, AActor* Instigator)패턴 통일 DamageEffectSetByCaller 키 —Data.Damage태그로 통일- 무기 데이터
PartName컨벤션 — 검은"Sword", 방패는"Shield" - 반응 시스템 트리거 위치 — Status GE가 적용되는 ASC 이벤트 리스너 (Step 7)
진행 순서 요약 (PR 단위)
| Step | 작업 | 의존성 | 예상 PR 수 |
|---|---|---|---|
| 1 | FSkillCombination 확장 | - | 1 |
| 2 | AnimNotify_BurstHit | 1 | 1 |
| 3 | PlayerCombatComponent 뼈대 | 1 | 1 |
| 4 | GA_Burst 리팩토링 | 1, 3 | 1 |
| 5-1 | Cleave 구현 (FFF, FFW) | 2, 3, 4, 6 | 1 |
| 5-2 | AoE 구현 (FWA) | 5-1 | 1 |
| 5-3 | Dash 구현 (AAF, AAW) | 5-1 | 1 |
| 5-4 | Projectile 구현 (AAA, FFA, WWA) | 5-1 | 1 |
| 5-5 | GroundEruption 구현 (WWW, WWF) | 5-1 | 1 |
| 6 | 상태 GE 작성 | - (Step 5와 병행 가능) | 1 |
| 7 | 반응 시스템 | 5, 6 완료 후 |