Files
DS-Combat_analy/분석참고자료/DS-전투시스템-어셋&코드.md

67 KiB
Raw Permalink Blame History

DS-전투시스템 종합분석

문서 개요

본 문서는 언리얼 엔진 에셋(DataTable, AnimMontage, Blueprint, CurveTable)을 JSON으로 익스포트하여 분석한 전투 로직 시스템에 대한 기술 문서입니다.

분석 대상 스토커: Hilda, Urud, Nave, Baran, Rio, Clad, Rene, Sinobu, Lian, Cazimord (10명)

작성 일자: 2025-10-23 익스포트 데이터: DS-전투밸런스_분석자료/20251023_114317/


목차

  1. 개요 및 Asset Export 시스템
  2. DataTable 구조
  3. AnimMontage 타이밍 시스템
  4. Blueprint Ability 및 캔슬 시스템
  5. GameplayEffect 메커니즘
  6. DT_Skill 특수 케이스
  7. 코드-어셋 통합 흐름
  8. JSON 사용 가이드

1. 개요 및 Asset Export 시스템

1.1 Asset Export to JSON 기능

언리얼 엔진 에셋은 기본적으로 바이너리 형식으로 저장되어 LLM이나 외부 분석 도구가 직접 접근할 수 없습니다. 이를 해결하기 위해 Asset Export to JSON 에디터 확장 기능을 개발하였습니다.

참고 문서: DS-전투밸런스_분석자료/DS-Asset_Export_to_JSON.md

주요 기능

  • 지원 에셋 타입: DataTable, Blueprint, AnimMontage, CurveTable
  • 프로젝트 설정 통합: 편집 → 프로젝트 설정 → 플러그인 → Asset Export to JSON
  • 타임스탬프 익스포트: 익스포트 히스토리 보관을 위한 타임스탬프 폴더 생성
  • 완전한 데이터 추출:
    • DataTable: 모든 행/열 데이터
    • Blueprint: 변수, 함수, 컴포넌트, 이벤트 그래프 노드 구조
    • AnimMontage: 섹션, 노티파이, 커스텀 프로퍼티, 슬롯 애니메이션
    • CurveTable: RichCurves 및 SimpleCurves 키 데이터

익스포트 실행

툴 → WorldStalker → Export Assets to JSON

출력 위치

Content/Exports/20251023_114317/
├── DataTable.json    (1,151 에셋)
├── Blueprint.json    (1,151 에셋)
├── AnimMontage.json  (809 에셋)
└── CurveTable.json   (8 에셋)

1.2 전투 로직 분석 범위

본 문서에서는 익스포트된 JSON 데이터를 기반으로 다음 전투 시스템을 분석합니다:

스토커별 전투 데이터

스토커 클래스 주요 특징
Hilda 전사 Counter 스킬, 방패 방어
Urud 원거리 Reload 시스템, 궁극기 'Explosion' 범위 피해
Nave 마법사 캐스팅 스킬, 궁극기 'Liberation' (DT_Skill 피해)
Baran 전사 중무장 탱커, Pulling 체인 메커니즘
Rio 암살자 Chain Score 시스템 (최대 3 스택)
Clad 성직자 힐링 및 언데드 특효
Rene 소환사 Spirit 소환, Lifesteal 효과
Sinobu 닌자 Shuriken 충전 시스템, 'Swap' 인술 (텔레포트)
Lian 레인저 Reload 시스템, Precision Aim (조준 시스템)
Cazimord 전사 Flash 스킬 스택, Parrying 시스템

분석 계층

스토커 전투 시스템
│
├── DataTable Layer (밸런스 데이터)
│   ├── DT_CharacterStat (기본 스탯, 스킬 목록)
│   ├── DT_Skill (스킬 데이터, 피해 배율, 쿨타임)
│   └── DT_CharacterAbility (기본 공격 어빌리티 매핑)
│
├── AnimMontage Layer (타이밍 데이터)
│   ├── 기본 공격 몽타주 (AM_PC_[Stalker]_B_Attack_*)
│   ├── 스킬 몽타주 (스킬별 애니메이션)
│   └── 노티파이 시스템
│       ├── ANS_AttackState_C (공격 상태, 피해 배율)
│       ├── AnimNotifyState_AttackWithEquip (히트 판정 타이밍)
│       ├── ANS_SkillCancel_C (스킬 캔슬 윈도우)
│       └── AN_SetAutoTarget_C (자동 타게팅)
│
├── Blueprint Ability Layer (로직 구현)
│   ├── GA_Attack (기본 공격)
│   ├── GA_Skill_* (스토커별 스킬 구현)
│   ├── Activation Order Group (우선순위 캔슬 시스템)
│   └── 특수 시스템 (Reload, Chain Score, Parrying 등)
│
└── GameplayEffect Layer (효과 적용)
    ├── GE_Attack_* (피해 효과)
    ├── GE_Skill_* (스킬 효과)
    └── GE_Buff/Debuff_* (버프/디버프)

1.3 JSON 참조 규칙

중요: JSON 파일은 에디터에서 익스포트한 결과물로, 소스 코드처럼 고정된 라인 번호가 없습니다.

올바른 참조 방법

Asset 이름으로 참조

DT_CharacterStat 어셋의 "hilda" 행
AM_PC_Hilda_B_Skill_SwordStrike 몽타주
GA_Skill_Hilda_SwordStrike_C 블루프린트

라인 번호로 참조하지 않음

DataTable.json:358143-358192  (X)

JSON 구조 예시

DataTable.json:

{
  "AssetName": "DT_CharacterStat",
  "RowStructure": "CharacterStatData",
  "Rows": [
    {
      "RowName": "hilda",
      "Data": {
        "name": "힐다",
        "defaultSkills": ["SK100201", "SK100202", "SK100204"],
        "subSkill": "SK100101",
        "ultimateSkill": "SK100301"
      }
    }
  ]
}

AnimMontage.json:

{
  "AssetName": "AM_PC_Hilda_B_Skill_SwordStrike",
  "SequenceLength": 1.8,
  "AnimNotifies": [
    {
      "NotifyStateClass": "ANS_SkillCancel_C",
      "TriggerTime": 1.3,
      "Duration": 0.5
    }
  ]
}

2. DataTable 구조

2.1 DT_CharacterStat (스토커 기본 스탯 및 스킬 매핑)

DT_CharacterStat은 각 스토커의 기본 스탯과 사용 가능한 스킬 목록을 정의합니다.

구조

필드 타입 설명
name String 스토커 이름 (한글)
jobName String 직업 (전사, 원거리, 마법사 등)
str Int 힘 (물리 공격력 영향)
dex Int 민첩 (공격 속도, 크리티컬 영향)
int Int 지능 (마법 공격력 영향)
con Int 체력 (HP, 방어력 영향)
wis Int 지혜 (마나, 마법 방어력 영향)
hP Float 기본 HP
mP Float 기본 MP
manaRegen Float 마나 재생 속도
defaultSkills Array 기본 스킬 ID 목록 (3-4개)
subSkill String 서브 스킬 ID (특수 스킬, 쿨타임 0초)
ultimateSkill String 궁극기 스킬 ID

스토커별 스탯 분포

전체 스탯 합계: 75 포인트 (모든 스토커 동일)

힘 중심 스토커 (STR 20+)

Hilda (전사):

STR: 20, DEX: 15, INT: 10, CON: 20, WIS: 10
HP: 100, MP: 50, Mana Regen: 0.2
Skills: SK100201 (Sword Strike), SK100202 (Counter), SK100204 (Provoke)
Sub: SK100101 (Blocking)
Ultimate: SK100301 (Blood Moon)

Baran (전사):

STR: 25, DEX: 10, INT: 5, CON: 25, WIS: 10
HP: 100, MP: 50, Mana Regen: 0.2
Skills: SK130204 (Pulling), SK130203 (Smash), SK130206 (Sword Stab)
Sub: SK130101 (Blocking)
Ultimate: SK130301 (Rock Breaker)
민첩 중심 스토커 (DEX 20+)

Urud (원거리):

STR: 15, DEX: 20, INT: 10, CON: 15, WIS: 15
HP: 100, MP: 50, Mana Regen: 0.2
Skills: SK110205 (Multi Shot), SK110204 (Poison Arrow), SK110201 (Make Trap), SK110207 (Reload)
Sub: SK110101 (Arrow Attack)
Ultimate: SK110301 (Explosion)

Rio (암살자):

STR: 15, DEX: 25, INT: 10, CON: 15, WIS: 10
HP: 100, MP: 50, Mana Regen: 0.2
Skills: SK140201 (Rapid Stab), SK140205 (Approach), SK140202 (Throwing Dagger)
Sub: SK140101 (Dropping Attack)
Ultimate: SK140301 (Sensitive)

Sinobu (닌자):

STR: 10, DEX: 25, INT: 10, CON: 15, WIS: 15
HP: 100, MP: 50, Mana Regen: 0.2
Skills: SK180202 (Bomb Talisman), SK180203 (Thunder Kick), SK180205 (Ninpo Change)
Sub: SK180101 (Shuriken)
Ultimate: SK180301 (Deflect)

Cazimord (전사):

STR: 15, DEX: 25, INT: 10, CON: 15, WIS: 10
HP: 100, MP: 50, Mana Regen: 0.2
Skills: SK170201 (Flash), SK170202 (Blade Storm), SK170203 (Burn)
Sub: SK170101 (Parrying)
Ultimate: SK170301 (Mana Stone Burn)

Lian (레인저):

STR: 10, DEX: 20, INT: 10, CON: 15, WIS: 20
HP: 100, MP: 50, Mana Regen: 0.2
Skills: SK190207 (Rapid Shot), SK190205 (Back Step), SK190201 (Dark Souls), SK190209 (Reload)
Sub: SK190101 (Charging Bow)
Ultimate: SK190301 (Manastone Silence)
지능 중심 스토커 (INT 20+)

Nave (마법사):

STR: 10, DEX: 10, INT: 25, CON: 10, WIS: 20
HP: 100, MP: 50, Mana Regen: 0.2
Skills: SK120201 (Magic Missile), SK120202 (Fire Wall), SK120206 (Wind Force)
Sub: SK120101 (Mana Restore)
Ultimate: SK120301 (Escape 4)

Rene (소환사):

STR: 10, DEX: 10, INT: 20, CON: 10, WIS: 25
HP: 100, MP: 50, Mana Regen: 0.2
Skills: SK160202 (Summon Ifrit), SK160206 (Summon Shiva), SK160203 (Poison Gas)
Sub: SK160101 (Scratching)
Ultimate: SK160301 (Mana Stone Carnival)
균형 스토커

Clad (성직자):

STR: 15, DEX: 10, INT: 10, CON: 20, WIS: 20
HP: 100, MP: 50, Mana Regen: 0.2
Skills: SK150206 (Holy Cure), SK150201 (Turn Undead), SK150202 (Holy Light)
Sub: SK150101 (Block)
Ultimate: SK150301 (Gold)

2.2 DT_Skill (스킬 상세 데이터)

DT_Skill은 각 스킬의 피해 배율, 쿨타임, 원소 타입, 사용 몽타주, 연결된 Ability 클래스 등을 정의합니다.

구조

필드 타입 설명
RowName String 스킬 ID (SK + 6자리 숫자)
stalkerName String 소유 스토커 이름 (소문자)
bIsUltimate Bool 궁극기 여부
skillName String 스킬 이름
skillDamageRate Float 기본 피해 배율 (1.0 = 100%)
skillManaCost Float 마나 소모량
coolTime Float 쿨타임 (초)
skillAttackType Enum 공격 타입 (PhysicalSkill, MagicalSkill, Normal)
skillElementType Enum 원소 타입 (None, Fire, Lightning, Poison, Water, Holy, Dark)
useMontages Array 사용할 몽타주 경로 목록
abilityClass String 연결된 GA_* 블루프린트 경로
gameplayEffectSet Array 적용할 GameplayEffect 목록

스킬 타입 분류

PhysicalSkill (물리 스킬)
  • 힘(STR) 또는 민첩(DEX) 스탯의 영향을 받음
  • 방어력(Defense)에 의해 감소
  • 예시: Hilda의 Sword Strike, Rio의 Rapid Stab, Cazimord의 Flash
MagicalSkill (마법 스킬)
  • 지능(INT) 또는 지혜(WIS) 스탯의 영향을 받음
  • 마법 저항력(MagicalResistancePer)에 의해 감소
  • 원소 타입에 따라 추가 저항력 적용 (Fire, Lightning, Poison 등)
  • 예시: Nave의 Magic Missile, Rene의 Summon Ifrit, Clad의 Turn Undead
Normal (일반/유틸리티)
  • 피해를 주지 않거나 특수 메커니즘을 가진 스킬
  • 스탯 배율 없이 고정 효과 또는 0 피해
  • 예시: Hilda의 Blocking, Urud의 Reload, Rio의 Approach

원소 타입별 특성

원소 저항 스탯 주요 사용 스토커
None - 대부분 (범용 스킬)
Lightning lightningResistancePer Hilda (Sword Strike), Sinobu (Thunder Kick)
Fire fireResistancePer Nave (Fire Wall)
Poison poisonResistancePer Urud (Poison Arrow), Rene (Poison Gas)
Water waterResistancePer -
Holy holyResistancePer Clad (Turn Undead), Lian (Dark Souls)
Dark darkResistancePer Rene (Poison Gas - Dark 속성도 보유)

스킬 예시

Hilda - SK100201 (Sword Strike):

{
  "RowName": "SK100201",
  "stalkerName": "hilda",
  "skillName": "Sword Strike",
  "skillDamageRate": 1.3,
  "coolTime": 6.0,
  "skillAttackType": "PhysicalSkill",
  "skillElementType": "Lightning",
  "useMontages": [
    "/Game/_Art/_Character/PC/Hilda/AnimMontage/Skill/AM_PC_Hilda_B_Skill_Ready.AM_PC_Hilda_B_Skill_Ready",
    "/Game/_Art/_Character/PC/Hilda/AnimMontage/Skill/AM_PC_Hilda_B_Skill_SwordStrike.AM_PC_Hilda_B_Skill_SwordStrike"
  ],
  "abilityClass": "/Game/Blueprints/Characters/Hilda/GA_Skill_Hilda_SwordStrike.GA_Skill_Hilda_SwordStrike_C"
}

Nave - SK120301 (Escape 4 / Liberation 궁극기):

{
  "RowName": "SK120301",
  "stalkerName": "nave",
  "bIsUltimate": true,
  "skillName": "Escape 4",
  "skillDamageRate": 1.0,
  "coolTime": 0.0,
  "skillAttackType": "MagicalSkill",
  "skillElementType": "None",
  "useMontages": [
    "/Game/_Art/_Character/PC/Nave/AnimMontage/Ultimate/AM_PC_Nave_B_Skill_Escape4.AM_PC_Nave_B_Skill_Escape4"
  ],
  "abilityClass": "/Game/Blueprints/Characters/Nave/GA_Skill_Nave_Escape4.GA_Skill_Nave_Escape4_C"
}

특수 사항: Nave의 궁극기는 AnimMontage의 노티파이가 아닌 DT_Skill의 skillDamageRate와 gameplayEffectSet에서 직접 피해를 정의합니다. (Section 6 참조)

Urud - SK110301 (Explosion 궁극기):

{
  "RowName": "SK110301",
  "stalkerName": "urud",
  "bIsUltimate": true,
  "skillName": "Explosion",
  "skillDamageRate": 1.0,
  "coolTime": 0.0,
  "skillAttackType": "Normal",
  "skillElementType": "None",
  "useMontages": [
    "/Game/_Art/_Character/PC/Urud/AnimMontage/Ultimate/AM_PC_Urud_B_Skill_Explosion.AM_PC_Urud_B_Skill_Explosion",
    "/Game/_Art/_Character/PC/Urud/AnimMontage/Base/AM_PC_Urud_B_Skill_Equipment.AM_PC_Urud_B_Skill_Equipment"
  ],
  "abilityClass": "/Game/Blueprints/Abilities/GA_Skill_Casting_Ultimate.GA_Skill_Casting_Ultimate_C"
}

특수 사항: Urud의 궁극기 'Explosion'은 투척한 돌이 적중 시 범위 피해를 줍니다. 피해는 AnimMontage의 노티파이 또는 GA_Skill Blueprint에서 처리됩니다.

2.3 DT_CharacterAbility (기본 공격 어빌리티 매핑)

DT_CharacterAbility는 각 스토커의 기본 공격(좌클릭)에 사용되는 Ability 클래스를 매핑합니다.

구조

필드 타입 설명
characterName String 스토커 이름
abilityClass String 기본 공격 Ability 경로

대부분의 스토커는 공통 GA_Attack 클래스를 사용하지만, 일부 스토커는 커스텀 공격 로직을 가집니다.

공통 기본 공격

GA_Attack 사용 스토커:

  • Hilda, Baran, Rio, Clad, Rene, Nave, Sinobu, Cazimord

기본 공격 로직:

  1. 장착한 무기의 montages 배열에서 몽타주 선택
  2. 콤보 시스템: 연속 입력 시 다음 몽타주로 체인
  3. AnimNotifyState_AttackWithEquip 노티파이에서 히트 판정
  4. ANS_AttackState_C 노티파이에서 피해 배율 적용

특수 기본 공격

Urud, Lian (원거리 스토커):

  • Ability: GA_Attack_Firearm (총기형 무기 전용)
  • 특징:
    • 탄약 시스템 (GameplayTag 기반 탄약 카운트)
    • 탄약 소진 시 자동으로 Reload 스킬 트리거
    • 조준 중 이동 속도 감소
    • Reload 스킬(SK110207, SK190209)로 재장전

2.4 스토커별 스킬 매핑 요약

스토커 기본 스킬 (3-4개) 서브 스킬 (쿨타임 0) 궁극기 특수 시스템
Hilda Sword Strike, Counter, Provoke Blocking Blood Moon Counter 반격, 방패 방어
Urud Multi Shot, Poison Arrow, Make Trap, Reload Arrow Attack Explosion Reload 시스템, 범위 피해 궁극기
Nave Magic Missile, Fire Wall, Wind Force Mana Restore Escape 4 캐스팅 스킬, Liberation 피해(DT_Skill)
Baran Pulling, Smash, Sword Stab Blocking Rock Breaker Pulling 체인, 중력 조작
Rio Rapid Stab, Approach, Throwing Dagger Dropping Attack Sensitive Chain Score (3 스택)
Clad Holy Cure, Turn Undead, Holy Light Block Gold 힐링, 언데드 특효
Rene Summon Ifrit, Summon Shiva, Poison Gas Scratching Mana Stone Carnival Spirit 소환, Lifesteal
Sinobu Bomb Talisman, Thunder Kick, Ninpo Change Shuriken Deflect Shuriken 충전, Swap 인술
Lian Rapid Shot, Back Step, Dark Souls, Reload Charging Bow Manastone Silence Reload 시스템, Precision Aim, 충전 3스택
Cazimord Flash, Blade Storm, Burn Parrying Mana Stone Burn Flash 스택, Parrying 반격

3. AnimMontage 타이밍 시스템

3.1 AnimMontage 노티파이 시스템 개요

AnimMontage는 애니메이션 재생 중 특정 타이밍에 게임 로직을 트리거하는 노티파이(Notify) 시스템을 제공합니다. 전투 시스템에서는 노티파이를 통해 다음을 구현합니다:

  • 공격 판정 타이밍: 무기가 적을 타격하는 정확한 프레임
  • 피해 배율 조정: 공격 구간별 피해량 증감
  • 스킬 캔슬 윈도우: 스킬을 중단하고 다음 행동으로 전환 가능한 시간대
  • 자동 타게팅: 적을 자동으로 추적하는 시점
  • 이동 제한: 스킬 사용 중 이동 속도 조절
  • 벽 충돌 체크: 근거리 공격 시 벽에 막히는지 검사

노티파이 타입

타입 설명 예시
Notify 특정 시점에 한 번 실행 AN_SetAutoTarget_C (자동 타게팅 활성화)
NotifyState 시작~종료 구간 동안 지속 ANS_AttackState_C (공격 상태 유지)

3.2 주요 노티파이 클래스

ANS_AttackState_C (공격 상태 및 피해 배율)

타입: NotifyState (구간 지속)

역할:

  • 공격 판정이 가능한 구간 정의
  • 피해 배율 조정 (AddNormalAttackPer 프로퍼티)

프로퍼티:

프로퍼티 타입 설명
TriggerTime Float 시작 시간 (초)
Duration Float 지속 시간 (초)
AddNormalAttackPer Float 피해 배율 증감 (%)

예시 - Baran 기본 공격 1타:

{
  "NotifyStateClass": "ANS_AttackState_C",
  "TriggerTime": 0.0,
  "Duration": 1.17,
  "CustomProperties": {
    "AddNormalAttackPer": "30.0"
  }
}

→ 0.0초부터 1.17초까지 공격 상태이며, 피해량이 +30% 증가

AnimNotifyState_AttackWithEquip (히트 판정 타이밍)

타입: NotifyState (구간 지속)

역할:

  • 무기의 궤적을 따라 히트 판정 수행
  • 다중 히트 지점 정의 (TimeArray, LocationArray, RotationArray)
  • 공격 타입 태그 지정 (Event.Attack.Normal, Event.Attack.Skill 등)

프로퍼티:

프로퍼티 타입 설명
TriggerTime Float 시작 시간 (초)
Duration Float 지속 시간 (초)
AttackTag GameplayTag 공격 타입 태그
TimeArray Array 다중 히트 시간 배열
LocationArray Array 히트 위치 배열
RotationArray Array 히트 방향 배열

예시 - Baran 기본 공격 1타 히트 판정:

{
  "NotifyStateClass": "AnimNotifyState_AttackWithEquip",
  "TriggerTime": 0.8,
  "Duration": 0.12,
  "CustomProperties": {
    "AttackTag": "(TagName=\"Event.Attack.Normal\")",
    "TimeArray": ["0.0", "0.033333", "0.066667", "0.1"],
    "LocationArray": ["(X=0,Y=0,Z=0)", "(X=20,Y=10,Z=5)", ...]
  }
}

→ 0.8초부터 0.92초까지 4개의 히트 포인트에서 판정 (0.033초 간격)

ANS_SkillCancel_C (스킬 캔슬 윈도우)

타입: NotifyState (구간 지속)

역할:

  • 스킬의 자연스러운 종료 타이밍 정의
  • 이 구간에서 같거나 낮은 Activation Order Group 스킬로 캔슬 가능
  • DPS 최적화에 중요한 역할

프로퍼티:

프로퍼티 타입 설명
TriggerTime Float 캔슬 윈도우 시작 시간 (초)
Duration Float 캔슬 윈도우 지속 시간 (초)

예시 - Hilda Sword Strike 스킬:

{
  "NotifyStateClass": "ANS_SkillCancel_C",
  "TriggerTime": 1.3,
  "Duration": 0.5
}

→ 1.3초부터 1.8초까지 캔슬 가능 (스킬 종료 구간)

중요: ANS_SkillCancel_C는 Activation Order Group 시스템과 독립적으로 작동합니다 (OR 조건). 자세한 내용은 Section 4.2 참조.

AN_SetAutoTarget_C (자동 타게팅)

타입: Notify (순간 실행)

역할:

  • 특정 시점에 가장 가까운 적을 자동으로 타게팅
  • 캐릭터 회전 및 카메라 방향 조정

예시:

{
  "NotifyClass": "AN_SetAutoTarget_C",
  "TriggerTime": 0.1
}

→ 0.1초 시점에 자동 타게팅 활성화

ANS_WeaponWallCheck_C (벽 충돌 검사)

타입: NotifyState (구간 지속)

역할:

  • 근거리 무기 공격 시 벽과의 충돌 검사
  • 벽에 막히면 공격 판정 무효화

ANS_DisableBlockingState_C (방어 불가 구간)

타입: NotifyState (구간 지속)

역할:

  • 특정 구간에서 방어(Blocking) 불가 상태로 만듦
  • 공격 모션 중 방어 전환 방지

3.3 스토커별 기본 공격 타이밍 분석

기본 공격은 좌클릭으로 실행되며, 대부분 3타 콤보로 구성됩니다. 각 타의 AnimMontage에서 피해 배율과 히트 판정 타이밍을 추출했습니다.

3타 콤보 총 소요 시간 (공격 속도 랭킹)

순위 스토커 1타 2타 3타 합계 특징
1 Rio 1.200s 1.300s 1.367s 3.867s 최고속 암살자
2 Sinobu 1.367s 1.333s 1.334s 4.034s 빠른 공격
3 Hilda 1.500s 1.500s 1.567s 4.567s 중간 속도
4 Nave 1.733s 1.667s 1.767s 5.167s 캐스터 타입
5 Cazimord 1.667s 1.900s 1.867s 5.434s 듀얼 소드
6 Baran 1.900s 1.700s 1.966s 5.566s 무거운 공격
7 Rene 2.000s 1.900s 2.000s 5.900s 느린 소환사
8 Clad 2.000s 2.000s 2.000s 6.000s 가장 느림

참고:

  • Urud, Lian: 원거리 총기형 공격 (발사 속도는 별도, Reload 필요)

기본 공격 피해 배율 (AddNormalAttackPer)

스토커 1타 2타 3타 특징
Baran +30% +35% +30% 가장 높은 피해 (탱커 타입)
Clad +30% +50% +30% 2타 강화 (성직자 평타)
Hilda +30% +30% +30% 일정한 피해
Cazimord -5% +15% +20% 3타 강화 (듀얼 소드)
Sinobu -30% +10% -30% 속도 우선, 낮은 피해
Rio -30% -20% -15% 낮은 피해 (속도로 보완)
Nave 0% 0% 0% 배율 없음 (마법 공격)
Rene 0% 0% 0% 배율 없음 (소환수 의존)

해석:

  • Baran, Clad: 느리지만 강력한 공격 (STR/CON 스토커)
  • Rio, Sinobu: 빠르지만 약한 공격 (DEX 스토커, 스킬 의존)
  • Nave, Rene: INT/WIS 스토커로 평타보다 스킬 중심

기본 공격 몽타주 예시

Hilda - AM_PC_Hilda_B_Attack_W01_01 (1타):

Duration: 1.5초
ANS_AttackState_C: 0.0~1.133초, AddNormalAttackPer: +30%
AnimNotifyState_AttackWithEquip: 0.733~0.867초 (히트 판정)
AN_SetAutoTarget_C: 0.1초 (자동 타게팅)

Rio - AM_PC_Rio_B_Attack_W01_01 (1타):

Duration: 1.2초
ANS_AttackState_C: 0.0~0.9초, AddNormalAttackPer: -30%
AnimNotifyState_AttackWithEquip: 0.4~0.533초 (빠른 히트)

Baran - AM_PC_Baran_B_Attack_W01_01 (1타):

Duration: 1.9초
ANS_AttackState_C: 0.0~1.17초, AddNormalAttackPer: +30%
AnimNotifyState_AttackWithEquip: 0.8~0.92초 (느린 히트)

Cazimord - AM_PC_Cazimord_B_Attack_W01_01 (1타):

Duration: 1.667초
ANS_AttackState_C: 0.0~0.900초, AddNormalAttackPer: -5%
AnimNotifyState_AttackWithEquip: 0.592~0.733초, 0.710~0.891초 (듀얼 소드 더블 히트)

3.4 스토커별 스킬 타이밍 분석

각 스토커의 주요 스킬 몽타주에서 타이밍 데이터를 추출했습니다.

Hilda (전사)

SK100201 - Sword Strike (AM_PC_Hilda_B_Skill_SwordStrike):

Duration: 1.8초
ANS_SkillCancel_C: 1.3~1.8초 (캔슬 윈도우 0.5초)
ANS_AttackState_C: 0.0~1.533초, AddNormalAttackPer: +100%
AnimNotifyState_AttackWithEquip: 0.6~0.8초

SK100202 - Counter (AM_PC_Hilda_B_Skill_Counter):

Duration: 2.567초
ANS_SkillCancel_C: 없음 (캔슬 불가)
특수: 반격 판정 노티파이 포함

SK100204 - Provoke (AM_PC_Hilda_B_Skill_Provoke):

Duration: 3.0초
ANS_SkillCancel_C: 없음
특수: 도발 범위 설정 노티파이

Urud (원거리)

SK110205 - Multi Shot (AM_PC_Urud_B_Skill_MultiArrow):

Duration: 2.0초
ANS_SkillCancel_C: 없음
AnimNotifyState_AttackWithEquip: 다중 화살 발사 타이밍

SK110204 - Poison Arrow (AM_PC_Urud_B_Skill_PoisonArrow):

Duration: 1.8초
ANS_SkillCancel_C: 없음
특수: Poison 상태 이상 적용

SK110207 - Reload (AM_PC_Urud_B_Skill_Reload):

Duration: 2.0초
ANS_SkillCancel_C: 없음
특수: 재장전 완료 노티파이 (탄약 충전)

Nave (마법사)

SK120201 - Magic Missile (AM_PC_Nave_B_Skill_MagicMissile):

Duration: 1.5초
ANS_SkillCancel_C: 없음
특수: 캐스팅 타입 (CanMove_CanRelease)

SK120202 - Fire Wall (AM_PC_Nave_B_Skill_FireWall):

Duration: 1.8초
ANS_SkillCancel_C: 없음
특수: 범위 화염 장판 생성

SK120301 - Escape 4 (Liberation 궁극기) (AM_PC_Nave_B_Skill_Escape4):

Duration: 3.5초
ANS_SkillCancel_C: 없음
특수: DT_Skill에서 피해 정의 (AnimMontage 노티파이 없음)

Baran (전사)

SK130204 - Pulling (AM_PC_Baran_B_Skill_Pulling):

Duration: 1.7초
ANS_SkillCancel_C: 1.276~1.700초 (캔슬 윈도우 0.424초)
특수: Pulling 체인 판정 (적 끌어당김)

SK130203 - Smash (AM_PC_Baran_B_Skill_Smash):

Duration: 2.0초
ANS_SkillCancel_C: 없음
AnimNotifyState_AttackWithEquip: 1.0~1.2초 (강타 판정)

SK130206 - Sword Stab (AM_PC_Baran_B_Skill_SwordStab):

Duration: 1.733초
ANS_SkillCancel_C: 1.660~1.733초 (캔슬 윈도우 0.073초, 매우 짧음)
AnimNotifyState_AttackWithEquip: 0.8~1.0초

Rio (암살자)

SK140201 - Rapid Stab (AM_PC_Rio_B_Skill_RapidStab):

Duration: 1.833초
ANS_SkillCancel_C: 1.513~1.833초 (캔슬 윈도우 0.32초)
특수: 빠른 연속 찌르기 (다중 히트)

SK140205 - Approach (AM_PC_Rio_B_Skill_Approach):

Duration: 1.5초
ANS_SkillCancel_C: 없음
특수: 돌진 이동 스킬 (피해 없음)

SK140202 - Throwing Dagger (AM_PC_Rio_B_Skill_ThrowingDagger):

Duration: 1.2초
ANS_SkillCancel_C: 없음
특수: 원거리 투척 공격

Clad (성직자)

SK150206 - Holy Cure (AM_PC_Clad_B_Skill_HolyCure):

Duration: 2.0초
ANS_SkillCancel_C: 없음
특수: 힐링 효과 (피해 없음)

SK150201 - Turn Undead (AM_PC_Clad_B_Skill_TurnUndead):

Duration: 2.5초
ANS_SkillCancel_C: 없음
특수: 언데드 특효 피해

SK150202 - Holy Light (AM_PC_Clad_B_Skill_HolyLight):

Duration: 2.0초
ANS_SkillCancel_C: 없음
특수: 범위 버프 효과

Rene (소환사)

SK160202 - Summon Ifrit (AM_PC_Rene_B_Skill_SummonIfrit):

Duration: 2.5초
ANS_SkillCancel_C: 없음
특수: Ifrit 소환수 생성

SK160206 - Summon Shiva (AM_PC_Rene_B_Skill_SummonShiva):

Duration: 2.5초
ANS_SkillCancel_C: 없음
특수: Shiva 소환수 생성

SK160203 - Poison Gas (AM_PC_Rene_B_Skill_PoisonGas):

Duration: 2.0초
ANS_SkillCancel_C: 없음
특수: 독 구름 장판 생성

Sinobu (닌자)

SK180202 - Bomb Talisman (AM_PC_Sinobu_B_Skill_BombTalisman):

Duration: 1.5초
ANS_SkillCancel_C: 없음
특수: 폭탄 부적 투척

SK180203 - Thunder Kick (AM_PC_Sinobu_B_Skill_ThunderKick):

Duration: 1.8초
ANS_SkillCancel_C: 없음
AnimNotifyState_AttackWithEquip: 0.6~0.8초
특수: 번개 속성 발차기

SK180205 - Ninpo Change (Swap) (AM_PC_Sinobu_B_Skill_NinpoChange):

Duration: 1.0초
ANS_SkillCancel_C: 없음
특수: 텔레포트 인술 (위치 교환)

Lian (레인저)

SK190207 - Rapid Shot (AM_PC_Lian_B_Skill_RapidShot1):

Duration: 2.626초
ANS_SkillCancel_C: 2.333~2.626초 (캔슬 윈도우 0.293초)
특수: 연속 사격 (6발)

SK190205 - Back Step Bow Attack (AM_PC_Lian_B_Skill_BackStepBowAttack):

Duration: 1.701초
ANS_SkillCancel_C: 1.492~1.701초 (캔슬 윈도우 0.209초)
특수: 백스텝 + 사격 (회피 기능)

SK190201 - Dark Souls (AM_PC_Lian_B_Skill_DarkSouls_NoCasting):

Duration: 2.0초
ANS_SkillCancel_C: 없음
특수: Holy 속성 관통 공격

SK190209 - Reload (AM_PC_Lian_B_Skill_Reload):

Duration: 2.0초
ANS_SkillCancel_C: 없음
특수: 재장전 (탄약 충전)

Cazimord (전사)

SK170201 - Flash (AM_PC_Cazimord_B_Skill_Flash, AM_PC_Cazimord_B_Skill_Flash_Active):

Flash (준비): Duration: 1.0초
Flash_Active (발동): Duration: 1.733초
ANS_SkillCancel_C: 1.001~1.733초 (Active 몽타주, 캔슬 윈도우 0.732초)
특수: Flash 스택 시스템 (최대 3스택)

SK170202 - Blade Storm (AM_PC_Cazimord_B_Skill_BladeStorm):

Duration: 3.0초
ANS_SkillCancel_C: 2.5~3.0초 (캔슬 윈도우 0.5초)
특수: 회전 범위 공격

SK170203 - Burn (AM_PC_Cazimord_B_Skill_Burn):

Duration: 2.5초
ANS_SkillCancel_C: 없음
특수: Fire 지속 피해

SK170101 - Parrying (서브 스킬) (AM_PC_Cazimord_B_Skill_Parrying):

Duration: 1.5초
ANS_SkillCancel_C: 없음
특수: 패링 성공 시 반격 + Flash 스택 충전

3.5 ANS_SkillCancel_C 보유 스킬 요약

전체 스킬 중 ANS_SkillCancel_C 노티파이를 가진 스킬은 7개뿐입니다. 기본 공격은 모두 캔슬 윈도우가 없습니다.

스토커 스킬 ID 스킬 이름 캔슬 시작 캔슬 종료 윈도우 크기
Hilda SK100201 Sword Strike 1.300s 1.800s 0.500s
Baran SK130204 Pulling 1.276s 1.700s 0.424s
Baran SK130206 Sword Stab 1.660s 1.733s 0.073s
Rio SK140201 Rapid Stab 1.513s 1.833s 0.320s
Lian SK190207 Rapid Shot 2.333s 2.626s 0.293s
Lian SK190205 Back Step 1.492s 1.701s 0.209s
Cazimord SK170202 Blade Storm 2.500s 3.000s 0.500s
Cazimord SK170201 Flash (Active) 1.001s 1.733s 0.732s

캔슬 윈도우가 없는 스토커 (5명):

  • Urud, Nave, Clad, Rene, Sinobu

이들은 Activation Order Group 시스템에만 의존하여 스킬 캔슬을 처리합니다. (Section 4.2 참조)

캔슬 윈도우 크기 특징:

  • 가장 긴 윈도우: Cazimord Flash_Active (0.732초) - 스택 충전 시스템에 유리
  • 가장 짧은 윈도우: Baran Sword Stab (0.073초) - 정밀한 타이밍 요구
  • 평균 윈도우: 약 0.4초

4. Blueprint Ability 및 캔슬 시스템

4.1 GA_* Blueprint Ability 구조

모든 스킬과 기본 공격은 UWSGameplayAbility를 상속한 Blueprint 클래스로 구현됩니다. 이 클래스들은 GA_로 시작하며 (GameplayAbility), 스킬 로직을 정의합니다.

UWSGameplayAbility 베이스 클래스

소스 위치: WorldStalker/Source/WorldStalker/AbilitySystem/WSGameplayAbility.h

주요 프로퍼티:

// 0: 그룹 없음, 1이상: 높을 수록 아래 상태를 무시하고, 같은 값이면 서로 교체됨
UPROPERTY(EditDefaultsOnly, Category = "WorldStalker")
uint8 ActivationOrderGroup = 0;

UPROPERTY(EditDefaultsOnly, Category = "WorldStalker")
bool bDisableOrderGroup = false;

UPROPERTY(EditDefaultsOnly, Category = "WorldStalker")
bool bCanSkillCancel = false;

UPROPERTY(EditDefaultsOnly, Category = "WorldStalker")
EWSAbilityActivationTrigger ActivationTrigger = EWSAbilityActivationTrigger::OnceInput;

Ability 클래스 분류

1. 공통 Ability (여러 스토커가 공유):

Ability 클래스 사용 스토커 용도
GA_Attack Hilda, Baran, Rio, Clad, Rene, Nave, Sinobu, Cazimord 기본 공격 (좌클릭)
GA_Attack_Firearm Urud, Lian 원거리 총기형 기본 공격 (탄약 시스템)
GA_Attack_Firearm_Reload Urud, Lian 재장전 (Reload 스킬)
GA_Skill_Common_Blocking Hilda, Baran, Clad 방패 방어 (서브 스킬)
GA_Skill_Casting_CanMove_CanRelease Nave (3개), Clad (3개), Rene (3개), Sinobu, Cazimord 이동 가능 캐스팅 스킬
GA_Skill_Casting_CantMove_CanRelease Urud (Make Trap) 이동 불가 캐스팅 스킬
GA_Skill_Casting_Ultimate Hilda, Urud, Clad, Rio, Rene, Lian 궁극기 (공통 로직)
GA_Skill_Ultimate_Base Sinobu 궁극기 베이스 클래스

2. 스토커 전용 Ability (특수 로직 구현):

각 스토커는 고유한 GA_Skill_[Stalker]_[SkillName] 클래스를 가집니다.

Ability 상속 계층

UGameplayAbility (언리얼 엔진 기본 클래스)
  └─ UWSGameplayAbility (C++ 베이스 클래스)
      ├─ GA_WSGameplayAbilityBase_C (Blueprint 베이스)
      │   ├─ GA_Attack_C (기본 공격)
      │   ├─ GA_Attack_Firearm_C (총기 공격)
      │   ├─ GA_Skill_Common_Blocking_C (방어)
      │   ├─ GA_Skill_Casting_* (캐스팅 스킬들)
      │   └─ GA_Skill_[Stalker]_[Skill]_C (스토커별 스킬)
      └─ ...

4.2 Activation Order Group 시스템

Activation Order Group은 스킬 활성화 우선순위를 정의하는 주요 캔슬 메커니즘입니다.

작동 원리

우선순위 규칙:

  1. 높은 그룹이 낮은 그룹을 캔슬: Group 3 스킬은 Group 1, 2 스킬을 언제든지 중단 가능
  2. 같은 그룹은 서로 교체 가능: Group 2 스킬끼리는 자유롭게 전환 가능
  3. 낮은 그룹은 높은 그룹을 캔슬 불가: Group 1 스킬은 Group 2 실행 중 발동 불가
  4. Group 0은 우선순위 없음: 다른 스킬에 의해 자유롭게 캔슬됨

C++ 코드 구현:

// WSGameplayAbility.h:189-191
uint8 GetActivationOrderGroup() const { return ActivationOrderGroup; }
void SetActivationOrderGroup(uint8 NewActivationOrderGroup) { ActivationOrderGroup = NewActivationOrderGroup; }
bool IsDisableOrderGroup() const { return bDisableOrderGroup; }

우선순위 예시

상황: Hilda가 Counter (Group 3) 실행 중

✅ 가능한 행동:
- Ultimate (Group 4) - 높은 그룹이므로 Counter 캔슬하고 발동
- Counter (Group 3) - 같은 그룹이므로 재사용 가능

❌ 불가능한 행동:
- Sword Strike (Group 2) - 낮은 그룹이므로 Counter 종료 전까지 대기
- 기본 공격 (Group 1) - 낮은 그룹이므로 Counter 종료 전까지 대기

일반적인 그룹 할당 패턴

Group 용도 예시
0 우선순위 없음 패시브, 버프, 기본 행동
2 이동/지원 스킬 Approach, Sway
3 방어/반격 스킬 Counter, Blocking, Parrying, Flash
4 일반 스킬 대부분의 공격 스킬
5 기본 공격 좌클릭 평타, 특수 공격
9 궁극기 Ultimate 스킬

스토커별 Activation Order Group 실제 값

다음은 Blueprint.json에서 추출한 10명 스토커의 실제 ActivationOrderGroup 값입니다.

Hilda (전사):

  • Group 4: Bash, SwordStrike
  • Group 0: BloodMoon_Active, SteelBlocking

Urud (궁수):

  • Group 5: ArrowAttack, MultiShot_Quick, PoisonArrow
  • Group 0: CampFire, Explosion_Active, MakeTrap, MultiShot, PierceShot, PoisonArrow_Active, SpeedUp

Nave (마법사):

  • Group 9: Escape4 (궁극기)
  • Group 4: ManaCharge_Casting
  • Group 0: Escape_Active, FireWall_Active, Invisible, MagicMissile_Active, MagicShield, TurnOff, WindForce

Baran (기사):

  • Group 9: Decision (궁극기)
  • Group 5: Pulling
  • Group 4: RockBreaker, Smash, SwordStab
  • Group 0: Prepare, Slasher

Rio (암살자):

  • Group 5: DroppingAttack
  • Group 4: Flashbang, RapidStab, ThrowingDagger
  • Group 2: Approach
  • Group 0: CatEyes, CorrosionDagger, Sensitive

Clad (성직자):

  • Group 0: Gold, HolyCure, HolyLight, HolyShield, HolyWall, Stigma, TurnUndead (모두 지원/버프 스킬)

Rene (소환사):

  • Group 5: Scratching
  • Group 0: BloodChange, BloodChange_Active, BloodSword_Active, ManaStoneCarnival, PoisonGas_Active, Slow_Active, SummonIfrit_Active, SummonShiva_Active

Sinobu (닌자):

  • Group 9: Silence (궁극기)
  • Group 5: Shuriken
  • Group 4: BombTalisman, MarkingSting, ThunderKick
  • Group 3: NinpoGecko_Casting
  • Group 0: Deflect, NinpoChange, NinpoFlame, SIlence_Active

Lian (레인저):

  • Group 5: BackStepBowAttack, ChargingBow, RapidShot
  • Group 4: DarkSouls
  • Group 0: CallingRat, MakeWoodCover, ManaStoneSilence_Active, MoreArrow, OneAim

Cazimord (검사):

  • Group 9: WingCutter (궁극기)
  • Group 4: BladeStorm, Burn, FrontKick, Parrying
  • Group 3: Flash
  • Group 2: BladeStorm_Perk, Sway, Sway_Perk
  • Group 0: Burn_Active

주요 발견:

  • 궁극기 (Group 9): Nave, Baran, Sinobu, Cazimord만 보유
  • 기본 공격 (Group 5): Urud, Baran, Rio, Rene, Sinobu, Lian이 사용
  • Clad와 Rene: 대부분 Group 0 (패시브/지원) 스킬로 구성
  • Cazimord: 가장 다양한 Group 분포 (0, 2, 3, 4, 9)

4.3 통합 캔슬 시스템 (OR 조건)

스킬 캔슬은 두 개의 독립적인 메커니즘으로 작동합니다. 둘 중 하나만 만족하면 캔슬이 가능합니다 (OR 조건).

메커니즘 1: Activation Order Group (주요 시스템)

정의 위치: GA_* Blueprint의 Class Defaults (C++ 프로퍼티)

작동 시점: 언제든지 (애니메이션 재생 중 어느 구간이든)

조건:

IF (새 스킬의 ActivationOrderGroup >= 현재 스킬의 ActivationOrderGroup)
  THEN 캔슬 가능

특징:

  • 우선순위 기반 시스템
  • 프레임 단위 정밀 제어 불필요
  • 대부분의 캔슬 처리 담당

메커니즘 2: ANS_SkillCancel_C (보조 시스템)

정의 위치: AnimMontage의 Notify State

작동 시점: 노티파이가 활성화된 시간 구간 (TriggerTime ~ TriggerTime+Duration)

조건:

IF (현재 시간이 ANS_SkillCancel_C 구간 내)
  AND (새 스킬의 ActivationOrderGroup >= 현재 스킬의 ActivationOrderGroup)
  THEN 캔슬 가능

특징:

  • 타이밍 기반 윈도우
  • 스킬의 "자연스러운 종료" 구간 정의
  • 같은 우선순위 스킬도 이 구간에서는 캔슬 가능

통합 로직 (의사 코드)

bool CanCancelCurrentSkill(GA_NewSkill, GA_CurrentSkill, CurrentTime)
{
  // 조건 1: Activation Order Group 우선순위 체크
  bool bHigherPriority = (GA_NewSkill.ActivationOrderGroup > GA_CurrentSkill.ActivationOrderGroup);

  // 조건 2: ANS_SkillCancel_C 윈도우 체크
  bool bInCancelWindow = false;
  if (GA_CurrentSkill.CurrentMontage->HasSkillCancelNotify())
  {
    float CancelStart = SkillCancelNotify.TriggerTime;
    float CancelEnd = CancelStart + SkillCancelNotify.Duration;
    bInCancelWindow = (CurrentTime >= CancelStart && CurrentTime <= CancelEnd);

    // 캔슬 윈도우 내에서는 같은 우선순위도 허용
    if (bInCancelWindow && GA_NewSkill.ActivationOrderGroup >= GA_CurrentSkill.ActivationOrderGroup)
      return true;
  }

  // OR 조건: 둘 중 하나만 만족하면 캔슬 가능
  return bHigherPriority || bInCancelWindow;
}

실전 예시

예시 1: Hilda - Sword Strike 스킬 사용 중 (Group 2)

상황 시간 새 입력 캔슬 가능? 이유
스킬 시작 0.5초 기본 공격 (Group 1) 낮은 우선순위
스킬 시작 0.5초 Counter (Group 3) 높은 우선순위 (메커니즘 1)
캔슬 윈도우 1.4초 다른 스킬 (Group 2) ANS_SkillCancel_C 구간 (메커니즘 2)
캔슬 윈도우 1.4초 기본 공격 (Group 1) 여전히 낮은 우선순위
스킬 종료 1.9초 모든 스킬 스킬 완전 종료

예시 2: Urud - Multi Shot 스킬 (ANS_SkillCancel_C 없음)

상황 새 입력 캔슬 가능? 이유
스킬 실행 중 일반 스킬 (같은 Group) ANS_SkillCancel_C 없음, 같은 우선순위
스킬 실행 중 Ultimate (Group 4) 높은 우선순위 (메커니즘 1만 작동)

4.4 주요 Ability 구현 분석

이전에 추출한 Blueprint.json 데이터를 기반으로 주요 Ability의 구조를 분석합니다.

GA_Attack (기본 공격)

사용 스토커: Hilda, Baran, Rio, Clad, Rene, Nave, Sinobu, Cazimord

부모 클래스: GA_WSGameplayAbilityBase_C

EventGraph 노드 수: 70개 (중간 복잡도)

주요 변수:

변수명 타입 설명
ComboIndex Int 현재 콤보 인덱스 (0~2)
MaxComboCount Int 최대 콤보 수 (기본 3)
ComboInputBuffer Bool 콤보 입력 버퍼 (선입력 지원)

로직:

  1. 장착한 무기의 montages 배열에서 ComboIndex에 해당하는 몽타주 재생
  2. 콤보 윈도우 내에 재입력 시 다음 콤보로 체인
  3. 최대 콤보 도달 또는 일정 시간 경과 시 ComboIndex 리셋

GA_Attack_Firearm (총기형 기본 공격)

사용 스토커: Urud, Lian

부모 클래스: GA_Attack_C

EventGraph 노드 수: 85개 (높은 복잡도)

주요 변수:

변수명 타입 설명
AmmoTag GameplayTag 탄약 카운트 태그 (Character.State.Ammo)
MaxAmmo Int 최대 탄약 수
bAutoReload Bool 탄약 소진 시 자동 재장전

특수 로직:

  1. 공격 시 AmmoTag 값을 1 감소
  2. 탄약이 0이면 공격 불가, 자동으로 Reload 스킬 트리거
  3. Reload 스킬 완료 시 AmmoTag를 MaxAmmo로 복구

예시 - Urud:

초기 탄약: 6발
발사 1~6발: AmmoTag = 6 → 5 → 4 → 3 → 2 → 1 → 0
탄약 소진: GA_Attack_Firearm_Reload 자동 실행
재장전 완료: AmmoTag = 6으로 복구

GA_Skill_Common_Blocking (방패 방어)

사용 스토커: Hilda, Baran, Clad

EventGraph 노드 수: 112개 (매우 높은 복잡도)

주요 변수:

변수명 타입 설명
BlockingStaminaCost Float 방어 시 스태미나 소모량
BlockingDamageReduction Float 피해 감소율 (%)
bPerfectBlockWindow Bool 완벽 방어 윈도우 활성화

특수 로직:

  1. 버튼을 누르고 있는 동안 방어 상태 유지 (WhileInput 트리거)
  2. 피격 시 BlockingDamageReduction만큼 피해 감소
  3. 스태미나가 0이면 방어 해제
  4. 완벽 방어 타이밍 성공 시 스태미나 소모 없음

GA_Skill_Casting_CanMove_CanRelease (이동 가능 캐스팅)

사용 스토커: Nave (3개 스킬), Clad (3개 스킬), Rene (3개 스킬), Sinobu, Cazimord

EventGraph 노드 수: 68개

주요 변수:

변수명 타입 설명
CastingTime Float 캐스팅 시간 (DT_Skill에서 가져옴)
bCanMoveWhileCasting Bool 캐스팅 중 이동 가능 (true)
bCanRelease Bool 버튼을 떼면 즉시 발동 (차징)

특수 로직:

  1. 버튼 누름: 캐스팅 시작 (몽타주 재생)
  2. 캐스팅 중 이동 속도 감소 (GE_WalkSpeed 적용)
  3. 버튼을 떼거나 CastingTime 경과 시 스킬 발동
  4. 캐스팅 중 다른 높은 우선순위 스킬로 캔슬 가능

4.5 스토커별 특수 시스템 구현

Hilda - Counter (반격 시스템)

Ability: GA_Skill_Knight_Counter_C

메커니즘:

  1. Counter 스킬 발동 시 짧은 시간 동안 "반격 판정" 상태
  2. 이 상태에서 피격 시 피해 무효화 + 자동 반격
  3. 반격 성공 시 추가 피해 (DT_Skill의 skillDamageRate 배율 적용)

AnimMontage: AM_PC_Hilda_B_Skill_Counter (Duration: 2.567초)

  • 반격 판정 구간: 0.3~0.8초 (0.5초 윈도우)
  • ANS_SkillCancel_C 없음 (강제로 끝까지 재생)

Urud & Lian - Reload 시스템

Ability: GA_Attack_Firearm_Reload_C

메커니즘:

  1. Reload 스킬 사용 시 재장전 몽타주 재생
  2. 재장전 완료 노티파이에서 AmmoTag 복구
  3. 재장전 중에는 공격 불가 (Blocking 상태)

특수 사항:

  • Urud: 탄약 6발, Reload 2.0초
  • Lian: 탄약 6발, Reload 2.0초 + Precision Aim (조준 시스템)

Lian의 Precision Aim:

  • 조준 버튼 누르면 줌 + 이동 속도 대폭 감소
  • 조준 중 명중률 증가 (히트박스 확대)

Rio - Chain Score 시스템 (3 스택)

Ability: GA_Skill_Rio_DroppingAttack_C (서브 스킬)

EventGraph 노드 수: 42개

주요 변수:

변수명 타입 설명
ChainScoreTag GameplayTag 체인 스코어 태그 (Character.State.ChainScore)
MaxChainScore Int 최대 스택 (3)
ChainScoreDamageBonus Float 스택당 피해 증가율

메커니즘:

  1. Dropping Attack (공중 낙하 공격) 성공 시 ChainScore +1
  2. 스택이 쌓일수록 다음 공격의 피해량 증가
  3. 최대 3스택 유지, 일정 시간 경과 또는 피격 시 리셋

예시:

Dropping Attack 성공 1회: ChainScore = 1, 다음 공격 피해 +10%
Dropping Attack 성공 2회: ChainScore = 2, 다음 공격 피해 +20%
Dropping Attack 성공 3회: ChainScore = 3, 다음 공격 피해 +30% (최대)

Rene - Spirit 소환 및 Lifesteal

Ability: GA_Skill_Rene_SummonIfrit_C, GA_Skill_Rene_SummonShiva_C

EventGraph 노드 수: Summon Ifrit (58개), Summon Shiva (55개)

메커니즘:

  1. 소환 스킬 사용 시 AI 제어 소환수 스폰
  2. 소환수는 독립적으로 적 공격
  3. Rene의 공격에 Lifesteal 효과 (GE_Lifesteal 적용)

Lifesteal:

  • 피해량의 일정 %를 HP로 회복
  • GameplayEffect로 구현 (Section 5 참조)

Sinobu - Shuriken 충전 시스템

Ability: GA_Skill_Sinobu_Shuriken_C (서브 스킬)

주요 변수:

변수명 타입 설명
ShurikenChargeTag GameplayTag 수리검 충전 태그
MaxShurikenCharge Int 최대 충전 수 (3)

메커니즘:

  1. 수리검 발사 시 ChargeTag -1
  2. 자동으로 시간 경과에 따라 충전 (1초당 1개)
  3. 충전이 0이면 발사 불가

Swap 인술 (SK180205 - Ninpo Change):

  • 적 위치와 자신의 위치를 순간 교환 (텔레포트)
  • 중력 조작 (Gravity = 0) 구간 존재

Lian - Charging Bow (3스택 충전)

Ability: GA_Skill_Lian_ChargingBow_C (서브 스킬)

EventGraph 노드 수: 116개 (가장 복잡한 서브 스킬)

주요 변수:

변수명 타입 설명
ChargeLevel Int 충전 레벨 (0~3)
ChargeTime Float 레벨당 충전 시간
ChargeDamageMultiplier Array 레벨별 피해 배율

메커니즘:

  1. 버튼 누름: 충전 시작
  2. 0.5초마다 ChargeLevel +1 (최대 3)
  3. 버튼 떼기: 현재 ChargeLevel에 해당하는 피해로 화살 발사
  4. ChargeLevel 3 (만충전): 피해 2배 + 관통 효과

피해 배율:

Level 0: 0.7x (즉발)
Level 1: 1.0x
Level 2: 1.5x
Level 3: 2.0x + 관통

Cazimord - Flash 스택 & Parrying

Flash 시스템 (SK170201):

Ability: GA_Skill_Cazimord_Flash_C

주요 변수:

변수명 타입 설명
FlashStackTag GameplayTag Flash 스택 태그
MaxFlashStack Int 최대 스택 (3)

메커니즘:

  1. Flash 스킬 사용 시 준비 몽타주 재생 (1.0초)
  2. 스택이 있으면 Flash_Active 몽타주 재생 (1.733초)
  3. Flash_Active는 빠른 돌진 + 피해
  4. 스택은 Parrying 성공 시 충전

ANS_SkillCancel_C: Flash_Active에만 존재 (1.001~1.733초, 0.732초 윈도우)

Parrying 시스템 (SK170101):

Ability: GA_Skill_Cazimord_Parrying_C

메커니즘:

  1. Parrying 발동 시 짧은 패링 판정 구간 (0.2초)
  2. 패링 성공 시:
    • 적 피해 무효화
    • 자동 반격 (높은 피해)
    • FlashStackTag +1
    • Parrying 스킬 쿨타임 즉시 리셋 (자기 자신 쿨타임 감소)

특수 사항:

  • Parrying은 쿨타임 감소 로직을 가진 유일한 스킬
  • 패링 실패 시에도 쿨타임 적용 (리스크-리워드)

5. GameplayEffect 메커니즘

5.1 GameplayEffect 개요

GameplayEffect는 언리얼 엔진의 Gameplay Ability System에서 캐릭터의 Attribute (HP, MP, 공격력 등)를 수정하는 메커니즘입니다. 모든 피해, 회복, 버프, 디버프는 GameplayEffect로 구현됩니다.

주요 GameplayEffect 타입

타입 지속 시간 용도 예시
Instant 즉시 적용 피해, 즉시 회복 GE_Attack_Physical (공격 피해)
Duration 정해진 시간 버프/디버프 GE_Buff_AttackSpeed (5초간 공격 속도 증가)
Infinite 영구 (수동 제거) 장비 효과, 패시브 GE_Equip_Weapon (무기 장착 보너스)

5.2 주요 GameplayEffect 클래스

GE_Attack_* (공격 피해)

DT_Skill의 gameplayEffectSet 또는 GA_ Blueprint에서 적용*

예시 - GE_Attack_Physical:

  • 타입: Instant
  • Modifier: HP -= (공격력 × skillDamageRate × 속성 배율)
  • 적용 시점: AnimNotifyState_AttackWithEquip 히트 판정 성공 시

피해 계산 공식 (일반적):

최종 피해 = 기본 공격력 × skillDamageRate × AddNormalAttackPer × (1 - 방어율) × 크리티컬 배율 × 속성 저항

GE_Skill_* (스킬 효과)

스킬별로 고유한 GameplayEffect를 가질 수 있습니다.

예시 - Hilda의 Sword Strike (SK100201):

  • GE_Skill_Hilda_SwordStrike: Lightning 속성 피해
  • Lightning 저항 적용: FinalDamage × (1 - Target.LightningResistancePer)

예시 - Rene의 Lifesteal:

  • GE_Lifesteal_Rene: Duration 타입, 일정 시간 동안 모든 공격에 흡혈 효과
  • Modifier: HP += (DamageDealt × LifestealRate)

GE_Buff/Debuff_* (버프/디버프)

예시 - GE_Buff_AttackSpeed:

  • 타입: Duration (5초)
  • Modifier: AttackSpeed += 20%
  • 시각 효과: 버프 아이콘 표시

예시 - GE_Debuff_Poison (Urud의 Poison Arrow):

  • 타입: Duration (10초)
  • Modifier: HP -= 10 (매 1초마다, Periodic)
  • 시각 효과: 독 이펙트 파티클

GE_Cooldown_* (쿨타임)

DT_Skill의 coolTime 값을 기반으로 자동 생성됩니다.

메커니즘:

  1. 스킬 사용 시 GE_Cooldown_[SkillID] 적용
  2. GameplayTag: Cooldown.Skill.[SkillID] 부여
  3. coolTime 초 경과 후 자동 제거
  4. 태그가 있는 동안 해당 스킬 사용 불가

쿨타임 감소:

  • WSGameplayAbility의 ReduceSkillCoolTime 함수 사용
  • 특정 룬/장비 효과로 쿨타임 % 감소 가능

GE_ManaCost_* (마나 소모)

DT_Skill의 skillManaCost 값을 기반으로 적용됩니다.

메커니즘:

  1. 스킬 CommitAbility 단계에서 마나 체크
  2. 마나 부족 시 스킬 발동 실패
  3. 마나 충분 시 GE_ManaCost 적용하여 MP 감소

5.3 GameplayEffectSet 구조

DT_Skill의 gameplayEffectSet 배열은 여러 GameplayEffect를 순차적으로 적용합니다.

구조:

"gameplayEffectSet": [
  {
    "applyTrigger": "OnActivation",
    "gameplayEffectClass": "/Game/Blueprints/Effects/GE_Skill_Buff.GE_Skill_Buff_C",
    "targetType": "Self"
  },
  {
    "applyTrigger": "OnHit",
    "gameplayEffectClass": "/Game/Blueprints/Effects/GE_Attack_Damage.GE_Attack_Damage_C",
    "targetType": "Target"
  }
]

applyTrigger 타입:

  • OnActivation: 스킬 활성화 시 즉시
  • OnHit: 타격 성공 시
  • OnEnd: 스킬 종료 시
  • Periodic: 주기적으로

targetType:

  • Self: 시전자에게 적용
  • Target: 타격 대상에게 적용
  • Area: 범위 내 모든 대상

5.4 특수 GameplayEffect 예시

Nave의 Fire Wall (지속 피해 장판)

메커니즘:

  1. Fire Wall 스킬 사용 시 바닥에 화염 장판 생성
  2. 장판 범위 내 적에게 GE_Debuff_FireWall_Periodic 적용
  3. Periodic 효과: 매 0.5초마다 Fire 속성 피해

GameplayEffect:

  • 타입: Duration (5초)
  • Period: 0.5초
  • Modifier: HP -= (BaseDamage × 0.2)

Baran의 Pulling (중력 조작)

메커니즘:

  1. Pulling 스킬 적중 시 GE_Pulling_Gravity 적용
  2. 적의 Gravity를 음수로 변경 (끌어당김)
  3. 0.5초 동안 적을 Baran 방향으로 이동

GameplayEffect:

  • 타입: Duration (0.5초)
  • Modifier: Gravity = -1000 (강제 이동)
  • Physics: AddImpulse (Baran 방향)

Clad의 Holy Cure (힐링)

메커니즘:

  1. Holy Cure 스킬 사용 시 GE_Heal_Holy 적용
  2. 자신 또는 아군의 HP 회복

GameplayEffect:

  • 타입: Instant
  • Modifier: HP += (HealAmount × WIS)
  • targetType: Self 또는 FriendlyTarget

6. DT_Skill 특수 케이스

6.1 Nave의 궁극기 - Liberation (Escape 4)

스킬 ID: SK120301

특수 사항: 대부분의 스킬은 AnimMontage의 노티파이(AnimNotifyState_AttackWithEquip)에서 피해를 처리하지만, Nave의 궁극기 'Liberation'은 DT_Skill의 데이터에서 직접 피해를 정의합니다.

일반 스킬의 피해 처리 (일반적 케이스)

흐름:

1. DT_Skill에서 skillDamageRate 정의 (예: 1.3)
2. AnimMontage의 AnimNotifyState_AttackWithEquip 노티파이 실행
3. 노티파이에서 AttackTag (Event.Attack.Skill) 트리거
4. GA_* Blueprint에서 skillDamageRate를 곱하여 피해 계산
5. GE_Attack_* GameplayEffect 적용

예시 - Hilda Sword Strike:

DT_Skill: skillDamageRate = 1.3
AnimMontage: AnimNotifyState_AttackWithEquip (TriggerTime: 0.6초)
Blueprint: ApplyAttackEffectToTarget 함수 호출
GameplayEffect: GE_Attack_Lightning 적용
최종 피해 = 기본 공격력 × 1.3 × Lightning 배율

Nave 궁극기의 피해 처리 (특수 케이스)

흐름:

1. DT_Skill의 gameplayEffectSet에 직접 피해 GameplayEffect 정의
2. AnimMontage에는 피해 노티파이 없음 (시각 효과만)
3. GA_Skill_Nave_Escape4 Blueprint에서 gameplayEffectSet 직접 적용
4. 범위 내 모든 적에게 피해 (Area 타겟)

DT_Skill 데이터 (SK120301):

{
  "RowName": "SK120301",
  "stalkerName": "nave",
  "bIsUltimate": true,
  "skillName": "Escape 4",
  "skillDamageRate": 1.0,
  "skillAttackType": "MagicalSkill",
  "skillElementType": "None",
  "useMontages": [
    "/Game/_Art/_Character/PC/Nave/AnimMontage/Ultimate/AM_PC_Nave_B_Skill_Escape4.AM_PC_Nave_B_Skill_Escape4"
  ],
  "abilityClass": "/Game/Blueprints/Characters/Nave/GA_Skill_Nave_Escape4.GA_Skill_Nave_Escape4_C",
  "gameplayEffectSet": [
    {
      "applyTrigger": "OnActivation",
      "gameplayEffectClass": "/Game/Blueprints/Effects/GE_Skill_Nave_Liberation.GE_Skill_Nave_Liberation_C",
      "targetType": "Area"
    }
  ]
}

GE_Skill_Nave_Liberation:

  • 타입: Instant
  • 범위: 반경 500 units
  • Modifier: HP -= (MagicPower × 1.0) × 4회 (4번의 텔레포트 각각 피해)
  • 특징: 텔레포트 이동 경로에 있는 모든 적 피해

AnimMontage (AM_PC_Nave_B_Skill_Escape4):

  • Duration: 3.5초
  • ANS_SkillCancel_C: 없음
  • 피해 판정 노티파이: 없음 (GameplayEffect에서 직접 처리)
  • 시각 효과 노티파이만 존재 (4회 텔레포트 이펙트)

왜 이렇게 구현했는가?

일반 스킬 방식의 한계:

  • AnimNotifyState_AttackWithEquip은 무기 궤적 기반 히트 판정
  • Nave의 궁극기는 텔레포트 경로 전체가 피해 범위
  • 무기가 없고, 정해진 궤적이 없음

gameplayEffectSet 직접 사용 장점:

  • 복잡한 범위 판정을 GameplayEffect 로직으로 처리
  • 4회 텔레포트의 각 경로마다 별도 피해 적용 가능
  • AnimMontage와 피해 로직 분리로 유연성 확보

6.2 Urud의 궁극기 - Explosion (범위 피해)

스킬 ID: SK110301

특수 사항: 투척한 돌이 지면 또는 적 적중 시 폭발하여 범위 피해를 줍니다.

메커니즘:

  1. 궁극기 활성화 시 투사체(돌) 스폰
  2. 투사체 충돌 시 Explosion Actor 생성
  3. Explosion Actor의 Overlap 이벤트에서 범위 내 적 검색
  4. 각 적에게 GE_Skill_Urud_Explosion 적용

특징:

  • 피해는 AnimMontage가 아닌 투사체 충돌 이벤트에서 처리
  • DT_Skill의 skillDamageRate는 기본 배율로 사용
  • 범위 중심부일수록 높은 피해 (거리 기반 감쇠)

7. 코드-어셋 통합 흐름

7.1 스킬 실행 전체 흐름

스킬이 입력부터 피해 적용까지 거치는 전체 과정을 정리합니다.

[1] 입력 처리
    ↓
[2] DT_CharacterStat에서 스킬 ID 조회
    ↓
[3] DT_Skill에서 스킬 데이터 로드
    ├─ skillDamageRate
    ├─ coolTime
    ├─ skillManaCost
    ├─ useMontages
    └─ abilityClass
    ↓
[4] GA_* Blueprint Ability 실행
    ├─ CanActivateAbility: 쿨타임/마나 체크
    ├─ ActivateAbility: 스킬 시작
    │   ├─ Activation Order Group 비교
    │   └─ 현재 스킬 캔슬 여부 결정
    ├─ CommitAbility: 마나/쿨타임 소모 확정
    │   ├─ GE_ManaCost 적용
    │   └─ GE_Cooldown 적용
    └─ PlayMontage: AnimMontage 재생
        ↓
[5] AnimMontage 재생
    ├─ ANS_AttackState_C: 공격 상태 활성화
    ├─ AnimNotifyState_AttackWithEquip: 히트 판정
    │   ├─ AttackTag 기반 이벤트 트리거
    │   └─ 범위 내 적 검색
    ├─ ANS_SkillCancel_C: 캔슬 윈도우 활성화
    └─ AN_SetAutoTarget_C: 자동 타게팅
        ↓
[6] 피해 계산 (GA_* Blueprint)
    ├─ FindSkillDataRow: DT_Skill 데이터 재조회
    ├─ CalculateSkillRate: 최종 피해 배율 계산
    │   ├─ skillDamageRate (기본)
    │   ├─ AddNormalAttackPer (몽타주)
    │   ├─ 장비 보정 (EquipSkillModify)
    │   └─ 룬 보정
    └─ ApplyAttackEffectToTarget: GameplayEffect 적용
        ↓
[7] GameplayEffect 적용
    ├─ GE_Attack_* 또는 GE_Skill_*
    ├─ Attribute Modifier 실행
    │   ├─ Target HP 감소
    │   ├─ 속성 저항 계산
    │   └─ 크리티컬 판정
    └─ 시각/사운드 효과 재생
        ↓
[8] 스킬 종료
    ├─ EndAbility: Ability 정리
    │   ├─ ActiveGameplayEffectHandle 제거
    │   └─ 카메라 모드 해제
    └─ 다음 입력 대기

7.2 캔슬 판정 상세 흐름

스킬 실행 중 새로운 입력이 들어왔을 때의 판정 과정:

새 스킬 입력 (예: Sword Strike → Counter)
    ↓
[1] 현재 실행 중인 Ability 확인
    ├─ CurrentAbility: GA_Skill_Hilda_SwordStrike
    ├─ CurrentAbility.ActivationOrderGroup: 2
    └─ CurrentTime: 0.5초 (몽타주 재생 중)
    ↓
[2] 새 Ability 정보 확인
    ├─ NewAbility: GA_Skill_Knight_Counter
    └─ NewAbility.ActivationOrderGroup: 3
    ↓
[3] 캔슬 가능 여부 판정 (OR 조건)
    ├─ 조건 A: Activation Order Group 비교
    │   └─ 3 > 2 → TRUE (높은 우선순위)
    ├─ 조건 B: ANS_SkillCancel_C 윈도우 체크
    │   ├─ CurrentMontage: AM_PC_Hilda_B_Skill_SwordStrike
    │   ├─ SkillCancel 구간: 1.3~1.8초
    │   └─ CurrentTime 0.5초 < 1.3초 → FALSE (윈도우 밖)
    └─ 최종 결과: TRUE (조건 A 만족)
    ↓
[4] 캔슬 실행
    ├─ CurrentAbility.EndAbility(bWasCancelled=true)
    ├─ NewAbility.ActivateAbility()
    └─ Counter 몽타주 재생 시작

7.3 C++ 코드와 어셋의 연동 지점

C++ 클래스 어셋 연동 방법
UWSGameplayAbility GA_* Blueprint Blueprint이 C++ 클래스 상속
ActivationOrderGroup (C++ 변수) GA_* Class Defaults Blueprint 에디터에서 값 설정
FSkillDataRow (C++ 구조체) DT_Skill DataTable DataTable의 RowStructure로 사용
ApplyAttackEffectToTarget (C++ 함수) AnimNotifyState_AttackWithEquip 노티파이에서 함수 호출
UGameplayEffect GE_* Blueprint GameplayEffect 서브클래스

핵심 연동 함수:

// WSGameplayAbility.cpp
FSkillDataRow* UWSGameplayAbility::FindSkillDataRow(FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo) const
{
  // DT_Skill에서 현재 스킬의 행 데이터 조회
  // abilityClass 경로로 역참조
}

void UWSGameplayAbility::ApplyAttackEffectToTarget(FGameplayAbilityTargetDataHandle TargetData, FGameplayTag InAttackTag, bool& bAttackFailMotion)
{
  // AnimMontage 노티파이에서 호출
  // DT_Skill 데이터 + 장비 보정 + 룬 보정 통합 계산
  // 최종 GameplayEffect 적용
}

8. JSON 사용 가이드

8.1 JSON 파일 구조 이해

익스포트된 JSON 파일들은 다음과 같은 구조를 가집니다:

DataTable.json:

[
  {
    "AssetName": "DT_CharacterStat",
    "AssetPath": "/Game/Blueprints/DataTable/DT_CharacterStat.DT_CharacterStat",
    "RowStructure": "CharacterStatData",
    "Rows": [
      {
        "RowName": "hilda",
        "Data": { ... }
      }
    ]
  }
]

AnimMontage.json:

[
  {
    "AssetName": "AM_PC_Hilda_B_Skill_SwordStrike",
    "AssetPath": "/Game/_Art/_Character/PC/Hilda/AnimMontage/Skill/AM_PC_Hilda_B_Skill_SwordStrike.AM_PC_Hilda_B_Skill_SwordStrike",
    "SequenceLength": 1.8,
    "Sections": [...],
    "AnimNotifies": [...]
  }
]

Blueprint.json:

[
  {
    "AssetName": "GA_Skill_Hilda_SwordStrike",
    "AssetPath": "/Game/Blueprints/Characters/Hilda/GA_Skill_Hilda_SwordStrike.GA_Skill_Hilda_SwordStrike",
    "ParentClass": "GA_WSGameplayAbilityBase_C",
    "Variables": [...],
    "Functions": [...],
    "EventGraphs": [...]
  }
]

8.2 데이터 추출 방법

Python을 사용한 JSON 파싱 예시

import json

# 1. DataTable에서 특정 스토커의 스킬 목록 조회
with open('DataTable.json', 'r', encoding='utf-8') as f:
    datatables = json.load(f)

# DT_CharacterStat 찾기
dt_char_stat = next((dt for dt in datatables if dt['AssetName'] == 'DT_CharacterStat'), None)

# Hilda의 스킬 목록
hilda_data = next((row for row in dt_char_stat['Rows'] if row['RowName'] == 'hilda'), None)
default_skills = hilda_data['Data']['defaultSkills']  # ["SK100201", "SK100202", "SK100204"]

# 2. DT_Skill에서 스킬 상세 정보 조회
dt_skill = next((dt for dt in datatables if dt['AssetName'] == 'DT_Skill'), None)

for skill_id in default_skills:
    skill_data = next((row for row in dt_skill['Rows'] if row['RowName'] == skill_id), None)
    print(f"{skill_id}: {skill_data['Data']['skillName']}, Damage: {skill_data['Data']['skillDamageRate']}")

특정 노티파이를 가진 AnimMontage 검색

with open('AnimMontage.json', 'r', encoding='utf-8') as f:
    montages = json.load(f)

# ANS_SkillCancel_C를 가진 모든 몽타주 찾기
cancel_montages = []
for montage in montages:
    for notify in montage.get('AnimNotifies', []):
        if notify.get('NotifyStateClass') == 'ANS_SkillCancel_C':
            cancel_montages.append({
                'montage': montage['AssetName'],
                'start': notify['TriggerTime'],
                'duration': notify['Duration']
            })

for item in cancel_montages:
    print(f"{item['montage']}: {item['start']}~{item['start']+item['duration']}초")

8.3 크로스 레퍼런스 (어셋 간 연결 추적)

스킬 하나의 전체 정보를 추적하는 방법:

# 1. DT_CharacterStat에서 스토커 → 스킬 ID
stalker_name = 'hilda'
skill_id = 'SK100201'  # DT_CharacterStat.hilda.defaultSkills[0]

# 2. DT_Skill에서 스킬 ID → 몽타주 경로, Ability 경로
skill_row = find_skill_by_id(skill_id)
montage_paths = skill_row['Data']['useMontages']
ability_path = skill_row['Data']['abilityClass']

# 3. AnimMontage.json에서 몽타주 경로 → 타이밍 데이터
montage_asset_name = montage_paths[1].split('.')[-1]  # "AM_PC_Hilda_B_Skill_SwordStrike"
montage_data = find_montage_by_name(montage_asset_name)

# ANS_SkillCancel_C 추출
cancel_notify = next((n for n in montage_data['AnimNotifies']
                      if n.get('NotifyStateClass') == 'ANS_SkillCancel_C'), None)

# 4. Blueprint.json에서 Ability 경로 → 로직 구조
ability_asset_name = ability_path.split('/')[-1].split('.')[0]  # "GA_Skill_Hilda_SwordStrike"
ability_data = find_blueprint_by_name(ability_asset_name)

# 최종 통합 정보
skill_info = {
    'id': skill_id,
    'name': skill_row['Data']['skillName'],
    'damage_rate': skill_row['Data']['skillDamageRate'],
    'cooldown': skill_row['Data']['coolTime'],
    'montage_duration': montage_data['SequenceLength'],
    'cancel_window': f"{cancel_notify['TriggerTime']}~{cancel_notify['TriggerTime']+cancel_notify['Duration']}" if cancel_notify else "없음",
    'ability_complexity': len(ability_data['EventGraphs'][0]['Nodes'])
}

8.4 주의사항

1. 라인 번호 참조 금지:

  • JSON 파일은 익스포트할 때마다 순서가 바뀔 수 있음
  • 항상 AssetName, RowName으로 검색

2. 경로 형식 이해:

언리얼 경로: /Game/Blueprints/Abilities/GA_Attack.GA_Attack_C
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 에셋 경로
                                             ^^^^^^^^^^^ 클래스 이름

JSON에서 찾을 때: "GA_Attack" (확장자 제외)

3. Blueprint Class Defaults 값 (ActivationOrderGroup) 포함:

  • EventGraph 노드 구조: JSON 포함
  • Class Defaults 값 (ActivationOrderGroup): JSON에 포함됨 (Variables 배열 내)
  • 추출 방법: Blueprint의 Variables 배열에서 "Name": "ActivationOrderGroup" 검색하여 DefaultValue 확인

4. 몽타주 경로 추출:

# DT_Skill.useMontages 배열
useMontages = [
    "/Script/Engine.AnimMontage'/Game/_Art/_Character/PC/Hilda/AnimMontage/Skill/AM_PC_Hilda_B_Skill_Ready.AM_PC_Hilda_B_Skill_Ready'",
    "/Script/Engine.AnimMontage'/Game/_Art/_Character/PC/Hilda/AnimMontage/Skill/AM_PC_Hilda_B_Skill_SwordStrike.AM_PC_Hilda_B_Skill_SwordStrike'"
]

# 몽타주 이름 추출
montage_names = [path.split('/')[-1].split('.')[0] for path in useMontages]
# ["AM_PC_Hilda_B_Skill_Ready", "AM_PC_Hilda_B_Skill_SwordStrike"]

8.5 유용한 분석 패턴

패턴 1: 모든 스킬의 평균 쿨타임 계산

skills = [row for dt in datatables if dt['AssetName'] == 'DT_Skill' for row in dt['Rows']]
avg_cooldown = sum(skill['Data']['coolTime'] for skill in skills) / len(skills)

패턴 2: 특정 스토커의 총 EventGraph 노드 수 (복잡도)

stalker_abilities = [bp for bp in blueprints if 'Hilda' in bp['AssetName']]
total_nodes = sum(len(eg['Nodes']) for bp in stalker_abilities for eg in bp['EventGraphs'])

패턴 3: ANS_SkillCancel_C 보유율

total_montages = len(montages)
cancel_montages = len([m for m in montages if any(n.get('NotifyStateClass') == 'ANS_SkillCancel_C' for n in m.get('AnimNotifies', []))])
cancel_rate = (cancel_montages / total_montages) * 100

문서 종료

본 문서는 언리얼 엔진 에셋(DataTable, AnimMontage, Blueprint)을 JSON으로 익스포트하여 분석한 WorldStalker 전투 로직 시스템의 기술 문서입니다.

작성 정보:

  • 작성일: 2025-10-23
  • 익스포트 데이터: DS-전투밸런스_분석자료/20251023_114317/
  • 분석 대상: 10명의 스토커 (Hilda, Urud, Nave, Baran, Rio, Clad, Rene, Sinobu, Lian, Cazimord)

추가 참고 문서:

  • DS-기획_메뉴얼-전투_로직.md: 전투 로직 기획 문서
  • DS-Asset_Export_to_JSON.md: Asset Export 시스템 가이드

문의: jinilkim@oneunivrs.com