2017 lines
67 KiB
Markdown
2017 lines
67 KiB
Markdown
|
|
# 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 시스템](#1-개요-및-asset-export-시스템)
|
|||
|
|
2. [DataTable 구조](#2-datatable-구조)
|
|||
|
|
3. [AnimMontage 타이밍 시스템](#3-animmontage-타이밍-시스템)
|
|||
|
|
4. [Blueprint Ability 및 캔슬 시스템](#4-blueprint-ability-및-캔슬-시스템)
|
|||
|
|
5. [GameplayEffect 메커니즘](#5-gameplayeffect-메커니즘)
|
|||
|
|
6. [DT_Skill 특수 케이스](#6-dt_skill-특수-케이스)
|
|||
|
|
7. [코드-어셋 통합 흐름](#7-코드-어셋-통합-흐름)
|
|||
|
|
8. [JSON 사용 가이드](#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**:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"AssetName": "DT_CharacterStat",
|
|||
|
|
"RowStructure": "CharacterStatData",
|
|||
|
|
"Rows": [
|
|||
|
|
{
|
|||
|
|
"RowName": "hilda",
|
|||
|
|
"Data": {
|
|||
|
|
"name": "힐다",
|
|||
|
|
"defaultSkills": ["SK100201", "SK100202", "SK100204"],
|
|||
|
|
"subSkill": "SK100101",
|
|||
|
|
"ultimateSkill": "SK100301"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**AnimMontage.json**:
|
|||
|
|
```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)**:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"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 궁극기)**:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"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 궁극기)**:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"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타:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"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<Float> | 다중 히트 시간 배열 |
|
|||
|
|
| `LocationArray` | Array<Vector> | 히트 위치 배열 |
|
|||
|
|
| `RotationArray` | Array<Rotator> | 히트 방향 배열 |
|
|||
|
|
|
|||
|
|
**예시** - Baran 기본 공격 1타 히트 판정:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"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 스킬:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"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 (순간 실행)
|
|||
|
|
|
|||
|
|
**역할**:
|
|||
|
|
- 특정 시점에 가장 가까운 적을 자동으로 타게팅
|
|||
|
|
- 캐릭터 회전 및 카메라 방향 조정
|
|||
|
|
|
|||
|
|
**예시**:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"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`
|
|||
|
|
|
|||
|
|
**주요 프로퍼티**:
|
|||
|
|
```cpp
|
|||
|
|
// 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++ 코드 구현**:
|
|||
|
|
```cpp
|
|||
|
|
// 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 캔슬 가능
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**특징**:
|
|||
|
|
- 타이밍 기반 윈도우
|
|||
|
|
- 스킬의 "자연스러운 종료" 구간 정의
|
|||
|
|
- 같은 우선순위 스킬도 이 구간에서는 캔슬 가능
|
|||
|
|
|
|||
|
|
#### 통합 로직 (의사 코드)
|
|||
|
|
|
|||
|
|
```cpp
|
|||
|
|
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<Float> | 레벨별 피해 배율 |
|
|||
|
|
|
|||
|
|
**메커니즘**:
|
|||
|
|
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를 순차적으로 적용합니다.
|
|||
|
|
|
|||
|
|
**구조**:
|
|||
|
|
```json
|
|||
|
|
"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)**:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"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 서브클래스 |
|
|||
|
|
|
|||
|
|
**핵심 연동 함수**:
|
|||
|
|
```cpp
|
|||
|
|
// 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**:
|
|||
|
|
```json
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"AssetName": "DT_CharacterStat",
|
|||
|
|
"AssetPath": "/Game/Blueprints/DataTable/DT_CharacterStat.DT_CharacterStat",
|
|||
|
|
"RowStructure": "CharacterStatData",
|
|||
|
|
"Rows": [
|
|||
|
|
{
|
|||
|
|
"RowName": "hilda",
|
|||
|
|
"Data": { ... }
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**AnimMontage.json**:
|
|||
|
|
```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**:
|
|||
|
|
```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 파싱 예시
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
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 검색
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
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 크로스 레퍼런스 (어셋 간 연결 추적)
|
|||
|
|
|
|||
|
|
스킬 하나의 전체 정보를 추적하는 방법:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
# 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. 몽타주 경로 추출**:
|
|||
|
|
```python
|
|||
|
|
# 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: 모든 스킬의 평균 쿨타임 계산**
|
|||
|
|
```python
|
|||
|
|
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 노드 수 (복잡도)**
|
|||
|
|
```python
|
|||
|
|
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 보유율**
|
|||
|
|
```python
|
|||
|
|
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
|