2025-10-23 22:03:00 +09:00
|
|
|
|
# 기획 메뉴얼 - 전투 로직
|
|
|
|
|
|
|
|
|
|
|
|
## 1. 데미지 계산
|
|
|
|
|
|
|
|
|
|
|
|
### 1.1 BaseDamage 계산 과정
|
|
|
|
|
|
|
|
|
|
|
|
> **코드 위치**:
|
|
|
|
|
|
> - `CharacterStatDataRow.h:104-107` - 기본 값 정의
|
|
|
|
|
|
> - `WSCharacterPlayer.cpp:3214-3245` - 1차 스탯 반영
|
|
|
|
|
|
> - `WSCharacterPlayer.cpp:3805-3806` - 장비 효과
|
|
|
|
|
|
> - `WSCharacterPlayer.cpp:4022` - 패시브 스탯 적용
|
|
|
|
|
|
> - `WSDamageCalculation.cpp:316-322, 543-613` - 최종 BaseDamage 결정
|
|
|
|
|
|
|
|
|
|
|
|
BaseDamage는 여러 단계를 거쳐 계산됩니다:
|
|
|
|
|
|
|
|
|
|
|
|
#### 1단계: 캐릭터 기본 값 (CharacterStatData)
|
|
|
|
|
|
|
|
|
|
|
|
**코드 위치**: `CharacterStatDataRow.h:104-107`
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
|
|
|
|
|
float PhysicalDamage = 0; // 캐릭터 기본 공격력
|
|
|
|
|
|
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
|
|
|
|
|
float MagicalDamage = 0; // 캐릭터 기본 마법 공격력
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- 캐릭터별 기본 PhysicalDamage, MagicalDamage 값
|
|
|
|
|
|
- DataTable에서 캐릭터별로 정의 (예: 힐다, 바란 등 각각 다른 기본값)
|
|
|
|
|
|
|
|
|
|
|
|
#### 2단계: 1차 스탯 반영
|
|
|
|
|
|
|
|
|
|
|
|
**코드 위치**: `WSCharacterPlayer.cpp:3214-3245 (UpdatePrimaryStats)`
|
|
|
|
|
|
|
|
|
|
|
|
- **Str (힘)** → 평타 피해율 (NormalDamagePer), 물리 스킬 피해율에 영향
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
CharacterSet->SetNormalDamagePer(NormalDamagePerCurve->Eval(PrimarySet->GetStr()));
|
|
|
|
|
|
CharacterSet->SetPhysicalSkillPer(PhysicalSkillPerCurve->Eval(PrimarySet->GetStr()));
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- **Int (지능)** → 마법 스킬 피해율에 영향
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
CharacterSet->SetMagicalSkillPer(MagicalSkillPerCurve->Eval(PrimarySet->GetInt()));
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- **Dex (민첩)** → 공격 속도, 이동 속도에 영향
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
CharacterSet->SetAttackSpeedPer(AttackSpeedPerCurve->Eval(PrimarySet->GetDex()));
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- **커브 테이블**: `WSData->PrimaryStat` 커브 테이블에서 1차 스탯 값 → 백분율 변환
|
|
|
|
|
|
|
|
|
|
|
|
#### 3단계: 장비 효과 적용
|
|
|
|
|
|
|
|
|
|
|
|
**코드 위치**: `WSCharacterPlayer.cpp:3805-3806, 4018-4022`
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// 장비 랜덤 옵션으로 PhysicalDamage, MagicalDamage 증가
|
|
|
|
|
|
AttrValueMap.Add(UCharacterSet::GetPhysicalDamageAttribute(),
|
|
|
|
|
|
FItemHelper::CalculateOption(EquipItem, EItemOption::PhysicalDamageInc));
|
|
|
|
|
|
AttrValueMap.Add(UCharacterSet::GetMagicalDamageAttribute(),
|
|
|
|
|
|
FItemHelper::CalculateOption(EquipItem, EItemOption::MagicalDamageInc));
|
|
|
|
|
|
|
|
|
|
|
|
// 패시브 스탯 (PhysicalDamagePer, MagicalDamagePer) 백분율 적용
|
|
|
|
|
|
float PhysicalDamagePer = AbilitySystemComponent->GetNumericAttribute(
|
|
|
|
|
|
UPassiveSet::GetPhysicalDamagePerAttribute()) * 0.01f;
|
|
|
|
|
|
AttrValueMap[UCharacterSet::GetPhysicalDamageAttribute()] +=
|
|
|
|
|
|
AttrValueMap[UCharacterSet::GetPhysicalDamageAttribute()] * PhysicalDamagePer;
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- 무기, 방어구, 악세서리 등 장비의 랜덤 옵션이 PhysicalDamage/MagicalDamage에 추가
|
|
|
|
|
|
- PassiveSet의 PhysicalDamagePer, MagicalDamagePer 백분율이 곱셈으로 적용
|
|
|
|
|
|
|
|
|
|
|
|
> **룬 시스템 영향** (섹션 5.4.1 참조):
|
|
|
|
|
|
> - **10201 분노**: PhysicalDamagePer +6~10%
|
|
|
|
|
|
> - **10301 폭풍**: MagicalDamagePer +6~10%
|
|
|
|
|
|
> - 이 단계에서 룬이 제공하는 패시브 스탯이 곱셈으로 적용됨
|
|
|
|
|
|
|
|
|
|
|
|
#### 4단계: Level 배율 적용
|
|
|
|
|
|
|
|
|
|
|
|
**코드 위치**: `WSDamageCalculation.cpp:316-322`
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
float PhysicalDamage = 0.0f;
|
|
|
|
|
|
ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(
|
|
|
|
|
|
DamageStatics().PhysicalDamageDef, EvaluateParameters, PhysicalDamage);
|
|
|
|
|
|
PhysicalDamage = PhysicalDamage * Level; // Level 곱셈
|
|
|
|
|
|
|
|
|
|
|
|
float MagicalDamage = 0.0f;
|
|
|
|
|
|
ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(
|
|
|
|
|
|
DamageStatics().MagicalDamageDef, EvaluateParameters, MagicalDamage);
|
|
|
|
|
|
MagicalDamage = MagicalDamage * Level; // Level 곱셈
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- 최종 PhysicalDamage, MagicalDamage에 스킬 레벨 곱셈
|
|
|
|
|
|
- Level이 0이면 1로 처리 (라인 310-314)
|
|
|
|
|
|
|
|
|
|
|
|
#### 5단계: 공격 타입별 BaseDamage 결정
|
|
|
|
|
|
|
|
|
|
|
|
**코드 위치**: `WSDamageCalculation.cpp:543-613`
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
if (EAttackType == EWSAttackType::Normal)
|
|
|
|
|
|
{
|
|
|
|
|
|
BaseDamage = PhysicalDamage;
|
|
|
|
|
|
SkillPer = NormalDamagePer;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (EAttackType == EWSAttackType::PhysicalSkill)
|
|
|
|
|
|
{
|
|
|
|
|
|
BaseDamage = PhysicalDamage;
|
|
|
|
|
|
SkillPer = PhysicalSkillPer + SkillDamagePer;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (EAttackType == EWSAttackType::MagicalSkill)
|
|
|
|
|
|
{
|
|
|
|
|
|
BaseDamage = MagicalDamage;
|
|
|
|
|
|
SkillPer = MagicalSkillPer + SkillDamagePer;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- **Normal (일반 공격)**: BaseDamage = PhysicalDamage
|
|
|
|
|
|
- **PhysicalSkill**: BaseDamage = PhysicalDamage
|
|
|
|
|
|
- **MagicalSkill**: BaseDamage = MagicalDamage
|
|
|
|
|
|
- **FixedSkill**: BaseDamage = 스킬 데이터에 정의된 고정값 (저항 무시)
|
|
|
|
|
|
|
|
|
|
|
|
#### 6단계: 던전 룰 배율 적용
|
|
|
|
|
|
|
|
|
|
|
|
**코드 위치**: `WSDamageCalculation.cpp:620-685`
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
switch (DungeonRule)
|
|
|
|
|
|
{
|
|
|
|
|
|
case EDungeonRule::EnemyAtkUp: // BaseDamage *= 1.4 (몬스터가 공격자일 때)
|
|
|
|
|
|
case EDungeonRule::EnemyAtkUpPlus: // BaseDamage *= 1.6
|
|
|
|
|
|
case EDungeonRule::EnemyDefDown: // BaseDamage *= 0.8
|
|
|
|
|
|
case EDungeonRule::EnemyDefDownPlus:// BaseDamage *= 0.7
|
|
|
|
|
|
case EDungeonRule::HeadWeak: // BaseDamage *= 1.5 (헤드샷일 때)
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 최종 공식 요약
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
최종 BaseDamage =
|
|
|
|
|
|
[캐릭터 기본값]
|
|
|
|
|
|
+ [장비 옵션 증가분]
|
|
|
|
|
|
× [1 + 패시브 스탯 백분율]
|
|
|
|
|
|
× [스킬 레벨]
|
|
|
|
|
|
× [던전 룰 배율]
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**예시 (물리 스킬)**:
|
|
|
|
|
|
```
|
|
|
|
|
|
캐릭터 기본 PhysicalDamage: 50
|
|
|
|
|
|
장비 옵션 증가: +30
|
|
|
|
|
|
패시브 PhysicalDamagePer: 20%
|
|
|
|
|
|
스킬 레벨: 3
|
|
|
|
|
|
던전 룰: 없음
|
|
|
|
|
|
|
|
|
|
|
|
최종 BaseDamage = ((50 + 30) × 1.20) × 3 = 96 × 3 = 288
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 1.2 일반 공격/스킬 데미지 계산 흐름
|
|
|
|
|
|
|
|
|
|
|
|
> **코드 위치**: `WSDamageCalculation.cpp:251-1238 (Execute_Implementation)`
|
|
|
|
|
|
|
|
|
|
|
|
#### 계산 흐름 개요
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
[1] BaseDamage 계산 (위 섹션 참조)
|
|
|
|
|
|
↓
|
|
|
|
|
|
[2] HitBox 판정 (머리/후면)
|
|
|
|
|
|
↓
|
|
|
|
|
|
[3] 치명타 판정
|
|
|
|
|
|
↓
|
|
|
|
|
|
[4] 둔기 배율 적용
|
|
|
|
|
|
↓
|
|
|
|
|
|
[5] 저항 타입 결정 (공격/원소 타입별)
|
|
|
|
|
|
↓
|
|
|
|
|
|
[6] 방어 상태 피해 감소
|
|
|
|
|
|
↓
|
|
|
|
|
|
[7] 최종 Damage 계산
|
|
|
|
|
|
↓
|
|
|
|
|
|
[8] 후면 공격 추가 배율
|
|
|
|
|
|
↓
|
|
|
|
|
|
[9] 최소 데미지 보장
|
|
|
|
|
|
↓
|
|
|
|
|
|
[10] 파티원 피해 제거
|
|
|
|
|
|
↓
|
|
|
|
|
|
[11] 실드 → 아머 → HP 순서로 적용
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 단계별 상세 설명
|
|
|
|
|
|
|
|
|
|
|
|
**[1] BaseDamage 계산** (라인 316-685)
|
|
|
|
|
|
- 위 "1.1 BaseDamage 계산 과정" 섹션 참조
|
|
|
|
|
|
- 캐릭터 기본값 + 장비 + 패시브 + Level + 던전 룰
|
|
|
|
|
|
|
|
|
|
|
|
**[2] HitBox 판정** (라인 470-510)
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// 머리/몸 판정
|
|
|
|
|
|
if (HitResult->BoneName == FName(TEXT("b_Head")))
|
|
|
|
|
|
{
|
|
|
|
|
|
IsHeadShot = true;
|
|
|
|
|
|
HitBoxRate = 1.2f + HeadAttackDamagePer * 0.01f;
|
|
|
|
|
|
HitBoxRate -= 0.5f * HeadShotDamReducePer * 0.01f; // 피격자의 머리 저항
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
HitBoxRate = 1.0f; // 몸
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 정면/후면 판정
|
|
|
|
|
|
IsFrontAttack = UWSAbilityBlueprintLibrary::IsFrontAttack(EffectCauser, Target, bUseOwnerRotation);
|
|
|
|
|
|
```
|
|
|
|
|
|
- **머리 기본 배율**: 1.2배
|
|
|
|
|
|
- **HeadAttackDamagePer**: 공격자의 머리 공격 피해 증가 (가산)
|
|
|
|
|
|
- **HeadShotDamReducePer**: 피격자의 머리 피해 감소 (절반만 적용)
|
|
|
|
|
|
- **후면 공격**: 이 단계에서는 HitBoxRate에 영향 없음 (후면 배율은 8단계에서 별도 적용)
|
|
|
|
|
|
|
|
|
|
|
|
> **룬 시스템 영향** (섹션 5.4.2 참조):
|
|
|
|
|
|
> - **10103 공략**: HeadAttackDamagePer +10~20% → 머리 공격 배율 1.2 → 1.3~1.4로 증가
|
|
|
|
|
|
|
|
|
|
|
|
**[3] 치명타 판정** (라인 512-527)
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
if (bUseCritical && FMath::FRandRange(0.0f, 100.0f) < CriticalPer)
|
|
|
|
|
|
{
|
|
|
|
|
|
isCritical = true;
|
|
|
|
|
|
CriticalDamageRate = (CriticalDamagePer * 0.01f) + (FMath::Rand() * CriticalDamageRange);
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- **CriticalPer**: 치명타 확률 (%)
|
|
|
|
|
|
- **CriticalDamagePer**: 치명타 피해 배율 (기본 150% 등)
|
|
|
|
|
|
- **CriticalDamageRange**: 치명타 피해 랜덤 범위
|
|
|
|
|
|
- **예시**: CriticalPer=30%, CriticalDamagePer=150%, Range=0.1
|
|
|
|
|
|
- 30% 확률로 치명타 발생
|
|
|
|
|
|
- 발생 시 1.5~1.6배 피해 (1.5 + random(0~0.1))
|
|
|
|
|
|
|
|
|
|
|
|
**[4] 둔기 배율** (라인 530-534)
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
float BluntRate = 1.0f;
|
|
|
|
|
|
if (EAttackType == EWSAttackType::Normal && SourceTags->HasTag(FGameplayTag::RequestGameplayTag("Equip.BluntWeapon")))
|
|
|
|
|
|
{
|
|
|
|
|
|
BluntRate = 1.2f;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- 둔기 무기 + 일반 공격일 때만 1.2배
|
|
|
|
|
|
- 스킬 공격에는 적용 안 됨
|
|
|
|
|
|
|
|
|
|
|
|
**[5] 저항 타입 결정** (라인 543-613)
|
|
|
|
|
|
|
|
|
|
|
|
공격 타입별로 적용되는 저항이 다릅니다:
|
|
|
|
|
|
|
|
|
|
|
|
| 공격 타입 | Resistance 1 | Resistance 2 |
|
|
|
|
|
|
|----------|--------------|--------------|
|
|
|
|
|
|
| Normal | PhysicalResistance | RangedResistance (원거리일 경우) |
|
|
|
|
|
|
| PhysicalSkill | PhysicalResistance | ElementResistance (속성별) |
|
|
|
|
|
|
| MagicalSkill | MagicalResistance | ElementResistance (속성별) |
|
|
|
|
|
|
| FixedSkill | 없음 | 없음 (저항 무시) |
|
|
|
|
|
|
|
|
|
|
|
|
- **ElementResistance**: Fire/Poison/Water/Lightning/Holy/Dark 중 하나
|
|
|
|
|
|
- **특수 케이스**: UsePhysicalDamageUseMagicResist=true면 물리 피해도 마법 저항 적용
|
|
|
|
|
|
- **저항 상한**: 각 저항은 최대 75%까지만 적용 (라인 709-710)
|
|
|
|
|
|
|
|
|
|
|
|
> **룬 시스템 영향** (섹션 5.4.3 참조):
|
|
|
|
|
|
> - **10202 방패**: PhysicalResistancePer +2~7%
|
|
|
|
|
|
> - **10302 수호**: MagicalResistancePer +2~7%
|
|
|
|
|
|
> - 룬으로 증가된 저항은 받는 피해 감소에 직접 영향
|
|
|
|
|
|
|
|
|
|
|
|
**[6] 방어 상태 피해 감소** (라인 769-795)
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
if (IsFrontAttack && TargetTags->HasTag(FGameplayTag::RequestGameplayTag("Character.State.Blocking")))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (EAttackType == EWSAttackType::Normal || EAttackType == EWSAttackType::PhysicalSkill)
|
|
|
|
|
|
{
|
|
|
|
|
|
Damage *= (1 - BlockedPhysicalDamageReducePer * 0.01f);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (EAttackType == EWSAttackType::MagicalSkill)
|
|
|
|
|
|
{
|
|
|
|
|
|
Damage *= (1 - BlockedMagicalDamageReducePer * 0.01f);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- **정면 + 방어 자세**일 때만 적용
|
|
|
|
|
|
- BlockedPhysicalDamageReducePer: 기본 100% (물리 공격 완전 방어)
|
|
|
|
|
|
- BlockedMagicalDamageReducePer: 기본 90% (마법 공격 90% 방어)
|
|
|
|
|
|
- **후면 공격은 방어 불가**
|
|
|
|
|
|
|
|
|
|
|
|
**[7] 최종 Damage 계산** (라인 706-718)
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// 저항 최대 75% 제한
|
|
|
|
|
|
ResistancePer1 = FMath::Min(ResistancePer1, 75.0f);
|
|
|
|
|
|
ResistancePer2 = FMath::Min(ResistancePer2, 75.0f);
|
|
|
|
|
|
|
|
|
|
|
|
// 몬스터 또는 Armor가 0일 경우
|
|
|
|
|
|
if (TargetTags->HasTag(TagEnemy) || Armor <= 0.0f)
|
|
|
|
|
|
{
|
|
|
|
|
|
Damage = Floor(BaseDamage * HitBoxRate * (SkillPer * 0.01) *
|
|
|
|
|
|
((1 - ResistancePer1 * 0.01) * (1 - ResistancePer2 * 0.01) * (1 - DamageReductionPer * 0.01)) *
|
|
|
|
|
|
CriticalDamageRate * (1 - TakeDamageReductionPer * 0.01) * (1 + TakeDamageIncreasePer * 0.01));
|
|
|
|
|
|
}
|
|
|
|
|
|
// Armor가 있을 경우 (플레이어)
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Damage = Floor((BaseDamage * BluntRate) * HitBoxRate * (SkillPer * 0.01) *
|
|
|
|
|
|
((1 - ResistancePer1 * 0.01) * (1 - ResistancePer2 * 0.01) * (1 - DamageReductionPer * 0.01)) *
|
|
|
|
|
|
CriticalDamageRate * (1 - TakeDamageReductionPer * 0.01) * (1 + TakeDamageIncreasePer * 0.01));
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**공식 분해**:
|
|
|
|
|
|
1. `BaseDamage * BluntRate` - 기본 피해 × 둔기 배율
|
|
|
|
|
|
2. `× HitBoxRate` - 머리/몸 배율
|
|
|
|
|
|
3. `× (SkillPer * 0.01)` - 스킬 피해율 (NormalDamagePer, PhysicalSkillPer 등)
|
|
|
|
|
|
4. `× (1 - ResistancePer1 * 0.01)` - 1차 저항 (물리/마법)
|
|
|
|
|
|
5. `× (1 - ResistancePer2 * 0.01)` - 2차 저항 (원소/원거리)
|
|
|
|
|
|
6. `× (1 - DamageReductionPer * 0.01)` - 방어력에 의한 피해 감소
|
|
|
|
|
|
7. `× CriticalDamageRate` - 치명타 배율 (크리티컬 아니면 1.0)
|
|
|
|
|
|
8. `× (1 - TakeDamageReductionPer * 0.01)` - 피격자의 받는 피해 감소
|
|
|
|
|
|
9. `× (1 + TakeDamageIncreasePer * 0.01)` - 피격자의 받는 피해 증가
|
|
|
|
|
|
10. `Floor()` - 소수점 버림
|
|
|
|
|
|
|
|
|
|
|
|
**[8] 후면 공격 추가 배율** (라인 793)
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
if (!IsFrontAttack && bUseTargetHitBox)
|
|
|
|
|
|
{
|
|
|
|
|
|
Damage *= (BackAttackDamagePer * 0.01f);
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- **후면 공격**일 때 BackAttackDamagePer 백분율 곱셈 (누적)
|
|
|
|
|
|
- HitBoxRate와는 별도로 적용
|
|
|
|
|
|
|
|
|
|
|
|
**[9] 최소 데미지 보장** (라인 763-766)
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
if (Damage < 1.0f && bUseDungeonRule)
|
|
|
|
|
|
{
|
|
|
|
|
|
Damage = 1.0f;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- 던전 룰이 적용될 때만
|
|
|
|
|
|
- 최소 1 데미지 보장
|
|
|
|
|
|
- 지속 피해에는 적용되지 않음
|
|
|
|
|
|
|
|
|
|
|
|
**[10] 파티원 피해 제거** (라인 850-868)
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
if (IsTargetParty)
|
|
|
|
|
|
{
|
|
|
|
|
|
Damage = 0.0f; // 파티원 간 피해 완전 차단
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- 같은 파티원에게는 피해 0
|
|
|
|
|
|
- 피격 이후 효과도 적용 안 됨
|
|
|
|
|
|
- 지역 효과(독 지대 등)는 여전히 적용됨
|
|
|
|
|
|
|
|
|
|
|
|
**[11] 실드 → 아머 → HP 적용** (라인 883-1047)
|
|
|
|
|
|
|
|
|
|
|
|
**실드 먼저 소모** (라인 883-888):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
ShieldDamage = Clamp(DamageNoResist, 0, Shield); // 저항 무시 피해로 계산
|
|
|
|
|
|
if (Shield > 0) {
|
|
|
|
|
|
Damage = Clamp(Damage - ShieldDamage, 0, Damage);
|
|
|
|
|
|
Shield -= ShieldDamage;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- 실드는 저항을 무시한 DamageNoResist로 계산
|
|
|
|
|
|
- 실드로 흡수한 만큼 Damage에서 차감
|
|
|
|
|
|
|
|
|
|
|
|
**아머 게이팅** (라인 1027-1035):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
if (Armor / ArmorMax > 0.5) {
|
|
|
|
|
|
DamageGating = (Armor - Damage) - (ArmorMax * 0.5);
|
|
|
|
|
|
if (DamageGating < 0) {
|
|
|
|
|
|
Damage += DamageGating; // 피해 감소
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
- 아머가 50% 이상일 때
|
|
|
|
|
|
- 한 번의 공격으로 50% 밑으로 떨어지지 않도록 보호
|
|
|
|
|
|
- **예시**: ArmorMax=100, Armor=80, Damage=40
|
|
|
|
|
|
- DamageGating = (80-40) - 50 = -10
|
|
|
|
|
|
- Damage = 40 + (-10) = 30 (10 감소)
|
|
|
|
|
|
- 최종 Armor = 80-30 = 50
|
|
|
|
|
|
|
|
|
|
|
|
**HP 적용** (라인 1038-1042):
|
|
|
|
|
|
- Armor가 0일 때만 HP에 피해
|
|
|
|
|
|
- 반죽음 상태에서는 HP에 -1씩만 적용
|
|
|
|
|
|
|
|
|
|
|
|
#### 계산 예시
|
|
|
|
|
|
|
|
|
|
|
|
**조건**:
|
|
|
|
|
|
- BaseDamage: 288 (위 예시)
|
|
|
|
|
|
- HitBoxRate: 1.2 (머리)
|
|
|
|
|
|
- SkillPer: 120% (PhysicalSkillPer)
|
|
|
|
|
|
- ResistancePer1: 30% (PhysicalResistance)
|
|
|
|
|
|
- ResistancePer2: 20% (FireResistance)
|
|
|
|
|
|
- DamageReductionPer: 15%
|
|
|
|
|
|
- CriticalDamageRate: 1.5 (치명타)
|
|
|
|
|
|
- BackAttackDamagePer: 150% (후면)
|
|
|
|
|
|
- Shield: 50
|
|
|
|
|
|
- Armor: 80 / 100
|
|
|
|
|
|
|
|
|
|
|
|
**계산**:
|
|
|
|
|
|
```
|
|
|
|
|
|
1. 기본 계산:
|
|
|
|
|
|
Damage = Floor(288 × 1.2 × 1.2 × 0.7 × 0.8 × 0.85 × 1.5)
|
|
|
|
|
|
= Floor(288 × 1.2 × 1.2 × 0.476)
|
|
|
|
|
|
= Floor(196.9)
|
|
|
|
|
|
= 196
|
|
|
|
|
|
|
|
|
|
|
|
2. 후면 배율:
|
|
|
|
|
|
Damage = 196 × 1.5 = 294
|
|
|
|
|
|
|
|
|
|
|
|
3. 실드 흡수:
|
|
|
|
|
|
Shield = 50 감소
|
|
|
|
|
|
Damage = 294 - 50 = 244
|
|
|
|
|
|
|
|
|
|
|
|
4. 아머 게이팅:
|
|
|
|
|
|
DamageGating = (80 - 244) - 50 = -214
|
|
|
|
|
|
Damage = 244 + (-214) = 30 (아머를 50으로 보호)
|
|
|
|
|
|
|
|
|
|
|
|
5. 최종:
|
|
|
|
|
|
Shield: 0
|
|
|
|
|
|
Armor: 50
|
|
|
|
|
|
HP: 변화 없음
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 1.3 지속 피해(DoT) 계산
|
|
|
|
|
|
|
|
|
|
|
|
> **코드 위치**: `WSDamageCalculation.cpp:427-437`
|
|
|
|
|
|
|
|
|
|
|
|
지속 피해는 일반 공격/스킬과는 별도의 계산 방식을 사용합니다.
|
|
|
|
|
|
|
|
|
|
|
|
#### DoT의 정의
|
|
|
|
|
|
|
|
|
|
|
|
- 캐릭터에게 지속적으로 피해를 주는 효과로써, 주로 스토커 스킬에 포함된다.
|
|
|
|
|
|
- 별도 명세가 없는한, 동일한 DD는 중첩되지 않고, 지속시간이 초기화 된다.
|
|
|
|
|
|
- 다른 DD끼리는 동시에 걸릴 수 있다.
|
|
|
|
|
|
- **DD는 적용 1초 후부터 피해가 발생하며, 1초 주기로 작동한다.**
|
|
|
|
|
|
|
|
|
|
|
|
#### 지속 피해 종류 및 공식
|
|
|
|
|
|
|
|
|
|
|
|
**중독 Poison**
|
|
|
|
|
|
- 유지 시간 동안 최대 체력의 n%만큼의 피해를 체력에 준다.
|
|
|
|
|
|
- 공식: `Maxhp*0.20*(1-DOTReduceRate)*(1-PoisonResistanceInc)/10`
|
|
|
|
|
|
- 10초 동안 적용되어 총 최대 체력의 20% 피해
|
|
|
|
|
|
|
|
|
|
|
|
**부식 Corrosion**
|
|
|
|
|
|
- 유지 시간 동안 방어구 최대 내구도의 n%만큼의 피해를 방어구 내구도에 준다.
|
|
|
|
|
|
- 공식: `MaxArmor*0.2*(1-DOTReduceRate)*(1-DarkResistanceInc)/10`
|
|
|
|
|
|
- **주의**: 암흑 저항(DarkResistance)이 적용됨
|
|
|
|
|
|
- 10초 동안 적용되어 총 최대 아머의 20% 피해
|
|
|
|
|
|
|
|
|
|
|
|
**화상 Burn** (중독 + 부식)
|
|
|
|
|
|
- 유지 시간 동안 최대 체력과 최대 방어구 내구도의 n%만큼의 피해를 체력과 방어구 내구도에 각각 준다.
|
|
|
|
|
|
- HP 공식: `Maxhp*0.1*(1-DOTReduceRate)*(1-FireResistanceInc)/10`
|
|
|
|
|
|
- Armor 공식: `MaxArmor*0.1*(1-DOTReduceRate)*(1-FireResistanceInc)/10`
|
|
|
|
|
|
- 10초 동안 적용되어 총 최대 체력/아머의 10% 피해
|
|
|
|
|
|
|
2025-10-27 17:04:37 +09:00
|
|
|
|
**출혈 Bleed**
|
|
|
|
|
|
- 10초 동안 1초 간격으로 체력이 -2씩 감소한다. 총 -20 체력. 출혈 저항이 없기 때문에 -2 감소는 절대값.
|
2025-10-23 22:03:00 +09:00
|
|
|
|
- 중독과의 차이점은 상대방의 최대 체력과 상관없이 총 피해량이 정해져 있다는 점.
|
|
|
|
|
|
|
|
|
|
|
|
**감전 ElectricShock** (미구현)
|
|
|
|
|
|
- 중독 효과 + 스킬을 사용할 수 없다. (일반 공격은 가능)
|
|
|
|
|
|
|
|
|
|
|
|
#### DoT 계산 예시
|
|
|
|
|
|
|
|
|
|
|
|
**조건**:
|
|
|
|
|
|
- HPMax: 1000
|
|
|
|
|
|
- DOTReducePer: 10%
|
|
|
|
|
|
- PoisonResistancePer: 25%
|
|
|
|
|
|
- 중독 지속 시간: 10초
|
|
|
|
|
|
|
|
|
|
|
|
**계산**:
|
|
|
|
|
|
```
|
|
|
|
|
|
1초당 피해 = 1000 × 0.20 × (1-0.1) × (1-0.25) / 10
|
|
|
|
|
|
= 1000 × 0.20 × 0.9 × 0.75 / 10
|
|
|
|
|
|
= 13.5
|
|
|
|
|
|
|
|
|
|
|
|
총 피해 (10초) = 13.5 × 10 = 135
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 1.4 힐 계산
|
|
|
|
|
|
|
|
|
|
|
|
> **코드 위치**: `WSHealCalculation.cpp:49-125`
|
|
|
|
|
|
|
|
|
|
|
|
힐은 마법 공격력 기반으로 계산됩니다.
|
|
|
|
|
|
|
|
|
|
|
|
#### 힐 계산 공식
|
|
|
|
|
|
|
|
|
|
|
|
**기본 공식** (라인 97-98):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// 힐 = 기본 힐량 + (마법공격력 × 스킬 계수) × (인트배율)
|
|
|
|
|
|
HealMagnitude = InComingHeal * Level + (MagicalDamage * (1.0 + SkillDamagePer * 0.01)) * (MagicalSkillPer * 0.01)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**구성 요소**:
|
|
|
|
|
|
1. **InComingHeal**: 스킬 데이터에 정의된 기본 힐량
|
|
|
|
|
|
2. **Level**: 스킬 레벨
|
|
|
|
|
|
3. **MagicalDamage**: 시전자의 마법 공격력 (2차 스탯)
|
|
|
|
|
|
4. **SkillDamagePer**: 패시브 스킬 피해 증가 (PassiveSet)
|
|
|
|
|
|
5. **MagicalSkillPer**: 지능(Int)에 의한 마법 스킬 피해율 (CharacterSet)
|
|
|
|
|
|
|
|
|
|
|
|
#### 과치유 방지
|
|
|
|
|
|
|
|
|
|
|
|
**코드** (라인 106-108):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
float TargetMaxHP = TargetASC->GetNumericAttribute(UCharacterSet::GetHPMaxAttribute());
|
|
|
|
|
|
float TargetHP = TargetASC->GetNumericAttribute(UCharacterSet::GetHPAttribute());
|
|
|
|
|
|
float HealAmount = FMath::Min(HealMagnitude, TargetMaxHP - TargetHP);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- 현재 HP + HealAmount가 MaxHP를 초과하지 않도록 제한
|
|
|
|
|
|
- 과치유는 발생하지 않음
|
|
|
|
|
|
|
|
|
|
|
|
#### 힐 무효
|
|
|
|
|
|
|
|
|
|
|
|
**코드** (라인 110-113):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
if (TargetASC->HasMatchingGameplayTag(FGameplayTag::RequestGameplayTag("Effect.IgnoreHeal")))
|
|
|
|
|
|
{
|
|
|
|
|
|
HealAmount = 0.0f;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- `Effect.IgnoreHeal` 태그가 있으면 힐 완전 무효
|
|
|
|
|
|
- 특정 디버프나 상태에서 힐 차단용
|
|
|
|
|
|
|
|
|
|
|
|
#### 궁극기 게이지 충전
|
|
|
|
|
|
|
|
|
|
|
|
**코드** (라인 118-123):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
if (!SourceASC->HasMatchingGameplayTag(FGameplayTag::RequestGameplayTag("Ability.Ultimate")))
|
|
|
|
|
|
{
|
|
|
|
|
|
float UltimateCurrentvalue = InstigatorCharacter->CharacterSet->GetUltimateCurrentValue();
|
|
|
|
|
|
float UltimateMaxValue = InstigatorCharacter->CharacterSet->GetUltimateMaxValue();
|
|
|
|
|
|
InstigatorCharacter->CharacterSet->SetUltimateCurrentValue(FMath::Min(HealAmount + UltimateCurrentvalue, UltimateMaxValue));
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- 궁극기 사용 중이 아닐 때만
|
|
|
|
|
|
- 실제 회복한 HealAmount만큼 궁극기 게이지 충전
|
|
|
|
|
|
- UltimateMaxValue를 초과하지 않음
|
|
|
|
|
|
|
|
|
|
|
|
#### 힐 계산 예시
|
|
|
|
|
|
|
|
|
|
|
|
**조건**:
|
|
|
|
|
|
- InComingHeal: 50 (스킬 기본 힐량)
|
|
|
|
|
|
- Level: 3
|
|
|
|
|
|
- MagicalDamage: 100
|
|
|
|
|
|
- SkillDamagePer: 15%
|
|
|
|
|
|
- MagicalSkillPer: 120%
|
|
|
|
|
|
- Target HP: 800 / 1000
|
|
|
|
|
|
|
|
|
|
|
|
**계산**:
|
|
|
|
|
|
```
|
|
|
|
|
|
1. HealMagnitude 계산:
|
|
|
|
|
|
HealMagnitude = (50 × 3) + (100 × 1.15) × 1.2
|
|
|
|
|
|
= 150 + (115 × 1.2)
|
|
|
|
|
|
= 150 + 138
|
|
|
|
|
|
= 288
|
|
|
|
|
|
|
|
|
|
|
|
2. 과치유 방지:
|
|
|
|
|
|
최대 회복 가능량 = 1000 - 800 = 200
|
|
|
|
|
|
HealAmount = Min(288, 200) = 200
|
|
|
|
|
|
|
|
|
|
|
|
3. 최종:
|
|
|
|
|
|
HP: 800 → 1000
|
|
|
|
|
|
궁극기 게이지: +200
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2. BaseDamage 구성요소
|
|
|
|
|
|
|
|
|
|
|
|
### 2.1 1차 스탯 (Primary Stats)
|
|
|
|
|
|
|
|
|
|
|
|
> **코드 위치**: `PrimarySet.h`
|
|
|
|
|
|
|
|
|
|
|
|
캐릭터 1차 스탯의 총합은 75가 되도록 한다.
|
|
|
|
|
|
|
|
|
|
|
|
- **힘** Str - 일반 공격 과 물리 스킬 피해량 에 영향을 준다.
|
|
|
|
|
|
- **민첩** Dex - 이동 속도 와 일반 공격 속도(평타) 에 영향을 준다.
|
|
|
|
|
|
- **지능** Int - 마법 스킬 시전속도 와 마법 스킬 피해량 에 영향을 준다.
|
|
|
|
|
|
- **체질** Con - 최대 체력 과 받는 지속 피해 감소 그리고 최대 지구력 에 영향을 준다.
|
|
|
|
|
|
- **지혜** Wis - 최대 마나 와 마나 소비량 에 영향을 준다.
|
|
|
|
|
|
|
|
|
|
|
|
### 2.2 2차 스탯 (Secondary Stats)
|
|
|
|
|
|
|
|
|
|
|
|
> **코드 위치**: `CharacterSet.h`
|
|
|
|
|
|
|
|
|
|
|
|
#### 기본 스탯
|
|
|
|
|
|
- 체력 HP
|
|
|
|
|
|
- 최대 체력 HPMax
|
|
|
|
|
|
- 마나 MP
|
|
|
|
|
|
- 최대 마나 MPMax
|
|
|
|
|
|
- 지구력 Stamina // 능력치 정보에서 안나옴
|
|
|
|
|
|
- 최대 지구력 StaminaMax
|
|
|
|
|
|
- 실드 Shield // 피해 흡수, 저항 무시
|
|
|
|
|
|
|
|
|
|
|
|
#### 피해 관련
|
|
|
|
|
|
- 물리 피해 PhysicalDamage
|
|
|
|
|
|
- 마법 피해 MagicalDamage
|
|
|
|
|
|
- 일반 공격 피해율 NormalDamagePer
|
|
|
|
|
|
- 물리 스킬 피해율 PhysicalSkillPer
|
|
|
|
|
|
- 마법 스킬 피해율 MagicalSkillPer
|
|
|
|
|
|
- 고정 스킬 피해율 FixedSkillPer
|
|
|
|
|
|
|
|
|
|
|
|
#### 방어 관련
|
|
|
|
|
|
- 방어력 Defense
|
|
|
|
|
|
- 고정 방어력 FixedDefense // 방어력 증가(%)의 영향을 받지 않는 방어력
|
|
|
|
|
|
- 방어력 비율 DefensePer
|
|
|
|
|
|
- 피해 감소율 DamageReductionPer // Defense에 의한 대미지 감소
|
|
|
|
|
|
- 방어구 내구도 Armor // 인게임 용어는 Armor Durability
|
|
|
|
|
|
- 최대 방어구 내구도 ArmorMax
|
|
|
|
|
|
- 콤비네이션 아머 CombinationArmor // 몬스터 전용
|
|
|
|
|
|
|
|
|
|
|
|
#### 속도 관련
|
|
|
|
|
|
- 이동속도 WalkSpeed
|
|
|
|
|
|
- 이동속도 비율 WalkSpeedPer
|
|
|
|
|
|
- 이동속도 수정값 MoveSpeedModify // 장비에 의해 변경
|
|
|
|
|
|
- 공격속도 AttackSpeedPer
|
|
|
|
|
|
- 스킬 시전 속도 SkillCastSpeedPer
|
|
|
|
|
|
|
|
|
|
|
|
#### 마나 관련
|
|
|
|
|
|
- 마나 회복 ManaRegen
|
|
|
|
|
|
- 마나 회복 비율 MPRegenPer
|
|
|
|
|
|
- 마나 소비 감소 // SkillCostReducePer
|
|
|
|
|
|
- 마나 쉴드 대미지 감소 MPDamageReducePer
|
|
|
|
|
|
|
|
|
|
|
|
#### 치명타 관련
|
|
|
|
|
|
- 치명타 확률 CriticalPer
|
|
|
|
|
|
- 치명타 피해 CriticalDamagePer
|
|
|
|
|
|
- 치명타 피해 감소 CriticalDamageReducePer
|
|
|
|
|
|
- 치명타 피해 범위 CriticalDamageRange
|
|
|
|
|
|
|
|
|
|
|
|
#### 특수 피해
|
|
|
|
|
|
- 후방 공격 피해율 BackAttackDamagePer
|
|
|
|
|
|
- 머리 공격 피해율 HeadAttackDamagePer // 때리는 입장
|
|
|
|
|
|
- 머리 피해 감소 HeadShotDamReducePer // 맞는 입장
|
|
|
|
|
|
- 방어 무시 피해율 IgnoreArmorDamagePer
|
|
|
|
|
|
- 방어 무시 피해의 아머 피해율 IgnoreArmorDamageToArmorPer
|
|
|
|
|
|
|
|
|
|
|
|
#### 저항
|
|
|
|
|
|
- 물리 저항률 PhysicalResistancePer
|
|
|
|
|
|
- 투사체 저항률 RangedResistancePer
|
|
|
|
|
|
- 마법 저항률 MagicalResistancePer
|
|
|
|
|
|
- 화염 저항률 FireResistancePer
|
|
|
|
|
|
- 독 저항률 PoisonResistancePer
|
|
|
|
|
|
- 물 저항률 WaterResistancePer
|
|
|
|
|
|
- 번개 저항률 LightningResistancePer
|
|
|
|
|
|
- 빛 저항률 HolyResistancePer
|
|
|
|
|
|
- 암흑 저항률 DarkResistancePer
|
|
|
|
|
|
- 지속 피해 저항률 DOTReducePer
|
|
|
|
|
|
|
|
|
|
|
|
#### 브레이크다운 시스템
|
|
|
|
|
|
- 브레이크다운 Breakdown // 브레이크다운 게이지 현재값
|
|
|
|
|
|
- 브레이크다운 최대값 BreakdownMax // 브레이크다운 게이지 최대값
|
|
|
|
|
|
- 브레이크다운 스턴 시간 BreakdownStunTime // 브레이크다운 발동 시 스턴 지속 시간
|
|
|
|
|
|
- 브레이크다운 리셋 시간 BreakdownResetTime // 브레이크다운 게이지 리셋 시간
|
|
|
|
|
|
|
|
|
|
|
|
#### 궁극기
|
|
|
|
|
|
- 궁극기 현재값 UltimateCurrentValue // 궁극기를 사용하기 위해서 충전해야 하는 포인트
|
|
|
|
|
|
- 궁극기 최대값 UltimateMaxValue
|
|
|
|
|
|
- 궁극기 회복 비율 UltimateRecoveryPer
|
|
|
|
|
|
|
|
|
|
|
|
#### 기타
|
|
|
|
|
|
- 장착 가능 장비 EquipableTypes
|
|
|
|
|
|
- 무기 종류: 검, 활, 지팡이, 대검, 단검, 둔기 // 1종을 할당
|
|
|
|
|
|
- 갑옷 종류: 천, 경갑, 중갑 // 2종을 할당
|
|
|
|
|
|
- 스킬 쿨타임 감소율 SkillCoolTimeReducePer
|
|
|
|
|
|
- 스킬 비용 감소율 SkillCostReducePer
|
|
|
|
|
|
- 가하는 피해량 감소 TakeDamageReductionPer // 리옌의 연화 디버프
|
|
|
|
|
|
- 가하는 피해량 증가 TakeDamageIncreasePer // 피해량 증가 스크롤
|
|
|
|
|
|
|
|
|
|
|
|
### 2.3 패시브 스탯 (비율 수정자)
|
|
|
|
|
|
|
|
|
|
|
|
> **코드 위치**: `PassiveSet.h`
|
|
|
|
|
|
|
|
|
|
|
|
패시브 스탯은 장비, 스킬, 퍽, **룬** 등을 통해 캐릭터의 능력치를 **백분율(%)로 수정**하는 속성들입니다. 주로 장비 랜덤 옵션, 스킬 효과, 캐릭터별 퍽(Perk) 시스템, **룬 시스템**에서 사용됩니다.
|
|
|
|
|
|
|
|
|
|
|
|
> **룬 시스템 영향** (섹션 5.3 참조):
|
|
|
|
|
|
> 룬 시스템은 PassiveSet 속성을 직접 수정하여 전투 능력을 강화합니다. 주요 룬 영향 속성:
|
|
|
|
|
|
> - PhysicalDamagePer, MagicalDamagePer, SkillDamagePer (피해 증가)
|
|
|
|
|
|
> - SkillCoolTimeReducePer, ManaCostPer, CastingTimePer (스킬 코스트)
|
|
|
|
|
|
> - NormalEnemyDamagePer, EliteEnemyDamagePer, BossEnemyDamagePer (몬스터 타입별)
|
|
|
|
|
|
> - APPer, PotionEffectPer, ThrowItemImpactRangePer 등
|
|
|
|
|
|
|
|
|
|
|
|
#### 공통 패시브 스탯 (PassiveSet.h:125-260)
|
|
|
|
|
|
|
|
|
|
|
|
**피해 관련**:
|
|
|
|
|
|
- PhysicalDamagePer // 물리 피해 증가율
|
|
|
|
|
|
- MagicalDamagePer // 마법 피해 증가율
|
|
|
|
|
|
- ArmorAttackDamagePer // 방어구 공격 피해 증가율
|
|
|
|
|
|
- SkillDamagePer // 스킬 피해 증가율
|
|
|
|
|
|
- TakenSkillDamagePer // 받는 스킬 피해 증가율
|
|
|
|
|
|
- InflictDamagePerOnStunTarget // 기절 대상에게 가하는 피해 증가율
|
|
|
|
|
|
- NormalEnemyDamagePer // 일반 몬스터에게 가하는 피해 증가율
|
|
|
|
|
|
- EliteEnemyDamagePer // 엘리트 몬스터에게 가하는 피해 증가율
|
|
|
|
|
|
- BossEnemyDamagePer // 보스 몬스터에게 가하는 피해 증가율
|
|
|
|
|
|
|
|
|
|
|
|
**방어 관련**:
|
|
|
|
|
|
- DefensePer // 방어력 증가율
|
|
|
|
|
|
- BreakArmorDefensePer // 방어구 파괴 방어 증가율
|
|
|
|
|
|
|
|
|
|
|
|
**속도 관련**:
|
|
|
|
|
|
- AttackSpeedPer // 공격 속도 증가율
|
|
|
|
|
|
- WalkSpeedPer // 이동 속도 증가율
|
|
|
|
|
|
|
|
|
|
|
|
**체력/마나/지구력 관련**:
|
|
|
|
|
|
- HPPer // 최대 체력 증가율
|
|
|
|
|
|
- MPPer // 최대 마나 증가율
|
|
|
|
|
|
- APPer // 지구력 증가율 (Armor Points)
|
|
|
|
|
|
- BlockingStaminaRate // 방어 시 지구력 소모 비율
|
|
|
|
|
|
|
|
|
|
|
|
**스킬/마나 코스트 관련**:
|
|
|
|
|
|
- ManaCostPer // 마나 소비 증가율 (음수면 감소)
|
|
|
|
|
|
- CastingTimePer // 시전 시간 증가율 (음수면 감소)
|
|
|
|
|
|
- CooldownTimePer // 쿨다운 시간 증가율 (음수면 감소)
|
|
|
|
|
|
|
|
|
|
|
|
**상태이상 관련**:
|
|
|
|
|
|
- TakenCCDurationTimePer // 받는 CC 지속 시간 증가율
|
|
|
|
|
|
|
|
|
|
|
|
**인터랙션 관련**:
|
|
|
|
|
|
- InteractionTimePer // 상호작용 시간 증가율 (음수면 감소)
|
|
|
|
|
|
- InteractionTakenDamagePer // 상호작용 중 받는 피해 증가율
|
|
|
|
|
|
- ChestInteractionTimePer // 상자 상호작용 시간 증가율
|
|
|
|
|
|
- DoorInteractionTimePer // 문 상호작용 시간 증가율
|
|
|
|
|
|
|
|
|
|
|
|
**어그로 및 스텔스**:
|
|
|
|
|
|
- AggroPer // 어그로 증가율
|
|
|
|
|
|
- CrouchWalkSoundPer // 웅크린 이동 소리 증가율
|
|
|
|
|
|
|
|
|
|
|
|
**부활 관련**:
|
|
|
|
|
|
- ReviveHPBonusRate // 부활 시 체력 보너스 비율
|
|
|
|
|
|
- ReviveTime // 부활 시간
|
|
|
|
|
|
|
|
|
|
|
|
**아이템 효과**:
|
|
|
|
|
|
- PotionEffectPer // 포션 효과 증가율
|
|
|
|
|
|
- ThrowItemImpactRangePer // 투척 아이템 범위 증가율
|
|
|
|
|
|
- ThrowEffectDurationPer // 투척 효과 지속 시간 증가율
|
|
|
|
|
|
- StatueEffectPer // 조각상 효과 증가율
|
|
|
|
|
|
|
|
|
|
|
|
**NPC 관련**:
|
|
|
|
|
|
- AttackDamagePerOnNpcKill // NPC 처치 시 공격 피해 증가율
|
|
|
|
|
|
|
|
|
|
|
|
#### 캐릭터별 전용 퍽 스탯 (PassiveSet.h:263-461)
|
|
|
|
|
|
|
|
|
|
|
|
각 스토커 캐릭터는 전용 퍽 스탯을 보유하고 있습니다:
|
|
|
|
|
|
- **Hilda** (힐다): 7개의 전용 퍽 (라인 265-292)
|
|
|
|
|
|
- **Urud** (우루드): 6개의 전용 퍽 (라인 297-320)
|
|
|
|
|
|
- **Nave** (네이브): 10개의 전용 퍽 (라인 325-364)
|
|
|
|
|
|
- **Baran** (바란): 8개의 전용 퍽 (라인 369-400)
|
|
|
|
|
|
- **Rio** (리오): 8개의 전용 퍽 (라인 405-436)
|
|
|
|
|
|
- **Clad** (클라드): 5개의 전용 퍽 (라인 441-460)
|
|
|
|
|
|
|
|
|
|
|
|
#### 범용 퍽 슬롯 (PassiveSet.h:466-488)
|
|
|
|
|
|
- Perk1 ~ Perk8: 범용 퍽 값 저장용 (용도는 게임플레이 효과에서 정의)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 3. 데미지 수정자
|
|
|
|
|
|
|
|
|
|
|
|
### 3.1 공격 타입 (AttackType)
|
|
|
|
|
|
|
|
|
|
|
|
> **코드 위치**: `SkillDataRow.h:13-21`
|
|
|
|
|
|
|
|
|
|
|
|
- 일반 공격(평타) Normal = 0
|
|
|
|
|
|
- 물리 스킬 PhysicalSkill = 1
|
|
|
|
|
|
- 마법 스킬 MagicalSkill = 2
|
|
|
|
|
|
- 고정 스킬 FixedSkill = 3 // 저항 무시 스킬용
|
|
|
|
|
|
- None = 4
|
|
|
|
|
|
|
|
|
|
|
|
### 3.2 원거리 타입 (RangedType)
|
|
|
|
|
|
|
|
|
|
|
|
- 평타가 원거리인지 아닌지를 판단
|
|
|
|
|
|
- 원거리 공격일 경우 RangedResistancePer 저항이 적용됨
|
|
|
|
|
|
|
|
|
|
|
|
### 3.3 원소 타입 (ElementType)
|
|
|
|
|
|
|
|
|
|
|
|
> **코드 위치**: `SkillDataRow.h:24-33`
|
|
|
|
|
|
|
|
|
|
|
|
- None = 0 // 무속성
|
|
|
|
|
|
- 화염 Fire = 1
|
|
|
|
|
|
- 독 Poison = 2
|
|
|
|
|
|
- 물 Water = 3
|
|
|
|
|
|
- 번개 Lightning = 4
|
|
|
|
|
|
- 빛 Holy = 5
|
|
|
|
|
|
- 암흑 Dark = 6
|
|
|
|
|
|
|
|
|
|
|
|
### 3.4 피해 종류 (DamageStatics)
|
|
|
|
|
|
|
|
|
|
|
|
- 일반 피해 NormalDamage
|
|
|
|
|
|
- 물리 피해 PhysicalDamage
|
|
|
|
|
|
- 마법 피해 MagicalDamage
|
|
|
|
|
|
- 치명 피해 CriticalDamage
|
|
|
|
|
|
- 후방 피해 BackAttackDamage
|
|
|
|
|
|
- 방어 무시 피해 IgnoreArmorDamage
|
|
|
|
|
|
- 갑옷 피해 IgnoreArmorDamageToArmor
|
|
|
|
|
|
- 머리 피해 HeadAttackDamage
|
|
|
|
|
|
|
|
|
|
|
|
### 3.5 저항 종류 (가급적 갑옷에 부여)
|
|
|
|
|
|
|
|
|
|
|
|
- MP 피해 저항 MPDamageReducePer
|
|
|
|
|
|
- 머리 피해 저항 HeadShotDamReducePer
|
|
|
|
|
|
- 지속 피해 저항 DOTReducePer
|
|
|
|
|
|
- 물리 저항 PhysicalResistancePer
|
|
|
|
|
|
- 마법 저항 MagicalResistancePer
|
|
|
|
|
|
- 원거리 저항 RangedResistancePer
|
|
|
|
|
|
- 화염 저항 FireResistancePer
|
|
|
|
|
|
- 독 저항 PoisonResistancePer
|
|
|
|
|
|
- 물 저항 WaterResistancePer
|
|
|
|
|
|
- 번개 저항 LightningResistancePer
|
|
|
|
|
|
- 빛 저항 HolyResistancePer
|
|
|
|
|
|
- 암흑 저항 DarkResistancePer
|
|
|
|
|
|
|
|
|
|
|
|
**저항 상한**: 모든 저항은 최대 75%까지만 적용됨
|
|
|
|
|
|
|
|
|
|
|
|
### 3.6 피격 부위 배율 (HitBoxRate)
|
|
|
|
|
|
|
|
|
|
|
|
> **코드 위치**: `WSDamageCalculation.cpp:473-510`
|
|
|
|
|
|
> **실제 구현**: 후면 공격 배율은 HitBoxRate가 아닌 BackAttackDamagePer 패시브로 조정됨
|
|
|
|
|
|
|
|
|
|
|
|
- **정면 공격** (IsFrontAttack = true)
|
|
|
|
|
|
- 머리 (IsHeadShot = true): `HitBoxRate = 1.2 + HeadAttackDamagePer * 0.01 - 0.5 * HeadShotDamReducePer * 0.01`
|
|
|
|
|
|
- 몸 (IsHeadShot = false): `HitBoxRate = 1.0`
|
|
|
|
|
|
|
|
|
|
|
|
- **후면 공격** (IsFrontAttack = false)
|
|
|
|
|
|
- 머리 (IsHeadShot = true): `HitBoxRate = 1.2 + HeadAttackDamagePer * 0.01 - 0.5 * HeadShotDamReducePer * 0.01`
|
|
|
|
|
|
- 몸 (IsHeadShot = false): `HitBoxRate = 1.0`
|
|
|
|
|
|
- **후면 추가 배율**: 최종 데미지에 `BackAttackDamagePer * 0.01` 곱셈 (코드 라인 793)
|
|
|
|
|
|
|
|
|
|
|
|
### 3.7 둔기 배율 (BluntRate)
|
|
|
|
|
|
|
|
|
|
|
|
> **코드 위치**: `WSDamageCalculation.cpp:530-534`
|
|
|
|
|
|
|
|
|
|
|
|
- 둔기 유형의 무기는 **1.2배** 데미지 (태그: `Equip.BluntWeapon`)
|
|
|
|
|
|
- 일반 공격(Normal) 타입일 때만 적용
|
|
|
|
|
|
|
|
|
|
|
|
### 3.8 쇼크 효과 (ShockMontageEffect)
|
|
|
|
|
|
|
|
|
|
|
|
플레이어가 쇼크 상태에 빠질 때 아래 몽타주 중 1개가 재생된다. (시간이 다름)
|
|
|
|
|
|
|
|
|
|
|
|
- 갑옷 완파 GE_ShockMotion_ArmorDestroy_Complete
|
|
|
|
|
|
- 갑옷 반파 GE_ShockMotion_ArmorDestroy_Partial
|
|
|
|
|
|
- 쇼크 대 GE_ShockMotion_Heavy
|
|
|
|
|
|
- 쇼크 중 GE_ShockMotion_Medium
|
|
|
|
|
|
- 쇼크 소 GE_ShockMotion_Weak
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 4. 특수 시스템
|
|
|
|
|
|
|
|
|
|
|
|
### 4.1 상태 이상(CC) & 능력치 하향(DeBuff)
|
|
|
|
|
|
|
|
|
|
|
|
#### 상태 이상CC 정의
|
|
|
|
|
|
|
|
|
|
|
|
- 캐릭터의 행동을 제한하거나 무력화 시키는 효과로써, 주로 스토커 스킬에 포함된다.
|
|
|
|
|
|
- 일반적으로 캐릭터들의 Motion Factor를 제어하며, 지속 시간을 보유하고 있다.
|
|
|
|
|
|
- 지속 시간의 표현을 위해 모션과 이펙트가 사용될 수 있다.
|
|
|
|
|
|
- GameplayTag로 `Character.State.*` 형태로 관리됨
|
|
|
|
|
|
|
|
|
|
|
|
#### 상태 이상CC의 종류
|
|
|
|
|
|
|
|
|
|
|
|
- **충격 Shock** (구현됨)
|
|
|
|
|
|
- 대상의 공격 모션을 중단 시킨다.
|
|
|
|
|
|
|
|
|
|
|
|
- **기절 Stun** (구현됨)
|
|
|
|
|
|
- 충격 Shock + 이동을 제한한다.
|
|
|
|
|
|
|
|
|
|
|
|
- **속박 Snare** (구현됨)
|
|
|
|
|
|
- 대상의 이동을 제한한다.
|
|
|
|
|
|
|
|
|
|
|
|
- **끌어당김 Grab** (구현됨)
|
|
|
|
|
|
- 기절 Stun + 시전자 방향으로 강제 이동시킨다.
|
|
|
|
|
|
|
|
|
|
|
|
- **밀쳐냄 KnockBack** (구현됨)
|
|
|
|
|
|
- 기절 Stun + 시전자의 반대 방향으로 강제 이동 시킨다.
|
|
|
|
|
|
- 이동 거리는 피격 대상의 위치를 기준으로 계산된다.
|
|
|
|
|
|
|
|
|
|
|
|
- **공포 Flee** (미구현)
|
|
|
|
|
|
- 충격 Shock + 시전자의 반대 방향으로 느리게 이동한다.
|
|
|
|
|
|
- 효과 지속시간 동안 피격 대상은 공격 행위를 할 수 없다.
|
|
|
|
|
|
|
|
|
|
|
|
- **수면 Sleep** (미구현)
|
|
|
|
|
|
- 기절 Stun과 같은 효과지만, 유지 시간 동안 대상이 다시 피격되면 해제 된다.
|
|
|
|
|
|
- 일반적으로 기절 Stun 보다는 유지 시간이 길다.
|
|
|
|
|
|
|
|
|
|
|
|
#### 능력치 하향DeBuff의 정의
|
|
|
|
|
|
|
|
|
|
|
|
- 캐릭터가 가진 능력치를 일시적으로 하향시키는 효과로써, 주로 스토커 스킬에 포함된다.
|
|
|
|
|
|
- 별도 명세가 없는한, 동일한 DeBuff는 중첩되지 않고, 지속시간이 초기화 된다.
|
|
|
|
|
|
- 다른 DeBuff끼리는 동시에 걸릴 수 있다.
|
|
|
|
|
|
|
|
|
|
|
|
#### 능력치 하향DeBuff의 종류
|
|
|
|
|
|
|
|
|
|
|
|
- **둔화 Slow** (구현됨)
|
|
|
|
|
|
- 유지 시간 동안 이동 속도가 n% 낮아진다.
|
|
|
|
|
|
- `WalkSpeedPer` 속성으로 구현
|
|
|
|
|
|
|
|
|
|
|
|
- **무장 해제 Disarm** (미구현)
|
|
|
|
|
|
- 유지 시간 동안 공격력이 n% 낮아진다.
|
|
|
|
|
|
|
|
|
|
|
|
### 4.2 방어 지구력 시스템
|
|
|
|
|
|
|
|
|
|
|
|
> **코드 위치**: `WSDamageCalculation.cpp:769-795` (방어 시스템)
|
|
|
|
|
|
> **Blueprint 경로 확인됨**: `D:\Work\WorldStalker\WorldStalker\Content\Blueprints\Abilities\GE_BlockingStateStamina.uasset`
|
|
|
|
|
|
|
|
|
|
|
|
#### 방어 상태 유지에 따른 효과
|
|
|
|
|
|
|
|
|
|
|
|
- **지구력 소모**
|
|
|
|
|
|
- BP경로: `/Game/Blueprints/Abilities/GE_BlockingStateStamina`
|
|
|
|
|
|
- 현재 설정 값: 0.2초 마다 -0.5 지구력
|
|
|
|
|
|
- **주의**: Blueprint 파일은 바이너리 형식이므로 설정값은 에디터에서 확인 필요
|
|
|
|
|
|
|
|
|
|
|
|
- **이동 속도 감소** (걷기만 가능하며 뛸 수 없다)
|
|
|
|
|
|
- BP경로: `/Game/Blueprints/Abilities/GE_AttackBlockedWalkSpeedDown`
|
|
|
|
|
|
- 현재 설정 값: 원래 걷는 속도의 70% 수준으로 이동한다.
|
|
|
|
|
|
- **주의**: Blueprint 파일은 바이너리 형식이므로 설정값은 에디터에서 확인 필요
|
|
|
|
|
|
|
|
|
|
|
|
- **방어 유지 가능 스토커**: 힐다, 바란, 클라드 (카지모르드는 아님)
|
|
|
|
|
|
|
|
|
|
|
|
#### 방어 성공에 따른 지구력 감소 값
|
|
|
|
|
|
|
|
|
|
|
|
- **근거리 일반 공격 방어**
|
|
|
|
|
|
- BP경로: `/Game/Blueprints/Abilities/GE_AttackBlocked`
|
|
|
|
|
|
- 현재 설정 값: 성공 시 -27.0 지구력
|
|
|
|
|
|
- **주의**: Blueprint 파일은 바이너리 형식이므로 설정값은 에디터에서 확인 필요
|
|
|
|
|
|
|
|
|
|
|
|
- **원거리 일반 공격 방어**
|
|
|
|
|
|
- BP경로: `/Game/Blueprints/Abilities/GE_AttackBlocked_Projectile`
|
|
|
|
|
|
- 현재 설정 값: 성공 시 -32.0 지구력
|
|
|
|
|
|
- **주의**: Blueprint 파일은 바이너리 형식이므로 설정값은 에디터에서 확인 필요
|
|
|
|
|
|
|
|
|
|
|
|
- **마법 공격 방어**
|
|
|
|
|
|
- BP경로: `/Game/Blueprints/Abilities/GE_AttackBlocked_Magic`
|
|
|
|
|
|
- 현재 설정 값: 성공 시 -35.0 지구력
|
|
|
|
|
|
- **주의**: Blueprint 파일은 바이너리 형식이므로 설정값은 에디터에서 확인 필요
|
|
|
|
|
|
|
|
|
|
|
|
#### 방어 피해 감소
|
|
|
|
|
|
|
|
|
|
|
|
> **코드 위치**: `WSDamageCalculation.cpp:769-795`
|
|
|
|
|
|
|
|
|
|
|
|
- **정면 방어 시** (IsFrontAttack && Character.State.Blocking 태그 보유)
|
|
|
|
|
|
- 일반 공격 (Normal): `Damage * (1 - BlockedPhysicalDamageReducePer * 0.01)` 감소
|
|
|
|
|
|
- 물리 스킬 (PhysicalSkill): `Damage * (1 - BlockedPhysicalDamageReducePer * 0.01)` 감소
|
|
|
|
|
|
- 마법 스킬 (MagicalSkill): `Damage * (1 - BlockedMagicalDamageReducePer * 0.01)` 감소
|
|
|
|
|
|
- **후면 공격은 방어 불가**
|
|
|
|
|
|
|
|
|
|
|
|
#### 지구력 자동 회복
|
|
|
|
|
|
|
|
|
|
|
|
- **전제**: 뛰는 상태 or 방어 상태가 아니어야 한다.
|
|
|
|
|
|
- 전제를 만족하고 n초 후에 m씩 지구력이 자동 회복 된다.
|
|
|
|
|
|
- BP경로: `/Game/Blueprints/Abilities/GE_StaminaRegen`
|
|
|
|
|
|
- **주의**: Blueprint 파일은 바이너리 형식이므로 설정값은 에디터에서 확인 필요
|
|
|
|
|
|
|
|
|
|
|
|
### 4.3 반죽음 (HalfDeath)
|
|
|
|
|
|
|
|
|
|
|
|
> **코드 위치**: `WSDamageCalculation.cpp:928-932`, `WSCharacterBase.h:178-180`
|
|
|
|
|
|
> **GameplayTag**: `Character.State.HalfDeath`
|
|
|
|
|
|
|
|
|
|
|
|
#### 반죽음의 정의
|
|
|
|
|
|
|
|
|
|
|
|
- 스토커의 체력HP = 0 이되면 n초 동안 반죽음 상태가 된다. 방어구 내구도와는 상관이 없다.
|
|
|
|
|
|
- 반죽음 상태가 되면 천천히 기면서 이동만 할 수 있고, 그 외 다른 행동(ex 공격)은 할 수 없다.
|
|
|
|
|
|
- 반죽음 상태가 없는 경우는 아래와 같다:
|
|
|
|
|
|
- 파티원이 없거나 or 생존한 파티원이 없을 경우 즉, 혼자 있을 경우에는 HP = 0이되면 바로 사망.
|
|
|
|
|
|
- `CanHalfDie()` 함수로 판별 (WSCharacterBase.h:178)
|
|
|
|
|
|
|
|
|
|
|
|
#### 반죽음 상태에서의 피해
|
|
|
|
|
|
|
|
|
|
|
|
- **피해량과는 상관 없이 총 3회의 피격을 견딜 수 있다.**
|
|
|
|
|
|
- 코드: 반죽음 상태에서는 피격 시 HP에 -1씩만 적용 (WSDamageCalculation.cpp:930)
|
|
|
|
|
|
- 상태 이상, 능력치 하향, 지속 피해 효과가 있다면 즉시 해제 된다.
|
|
|
|
|
|
- **파티원의 공격은 적용되지 않음** (코드 라인 928: `IsTargetParty` 체크)
|
|
|
|
|
|
|
|
|
|
|
|
#### 반죽음 → 사망 판정
|
|
|
|
|
|
|
|
|
|
|
|
- 반죽음 유지 시간이 모두 지나거나 or 피격을 3회 이상 받으면 사망 상태가 된다.
|
|
|
|
|
|
|
|
|
|
|
|
#### 반죽음 → 부활 판정
|
|
|
|
|
|
|
|
|
|
|
|
- 사망 판정을 받기 전에 파티원이 근처에 와서 F키를 눌러 부활시켜주면 된다. (일정 시간 필요)
|
|
|
|
|
|
- 반죽음 이전에 방어구 내구도가 남아 있었다면 이를 보존시켜준다.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 5. 룬 시스템
|
|
|
|
|
|
|
|
|
|
|
|
> **코드 위치**:
|
|
|
|
|
|
> - `WSGameplayAbility.h:209, 268` - 룬 데이터 조회 함수
|
|
|
|
|
|
> - `WSGameplayAbility.cpp:1525-1550` - 룬 데이터 검색 구현
|
|
|
|
|
|
> - **DT_Rune, DT_RuneGroup** DataTable 어셋 (DataTable.json 파일에 익스포트됨)
|
|
|
|
|
|
|
|
|
|
|
|
### 5.1 룬 시스템 개요
|
|
|
|
|
|
|
|
|
|
|
|
룬은 플레이어가 장착하여 전투 능력과 탐험 능력을 강화하는 장비 시스템입니다. 각 룬은 레벨 1부터 5까지 업그레이드가 가능하며, 레벨이 올라갈수록 효과가 강화됩니다.
|
|
|
|
|
|
|
|
|
|
|
|
#### 기본 메커니즘
|
|
|
|
|
|
|
|
|
|
|
|
- **장착 슬롯**: 총 5개의 룬 슬롯 보유
|
|
|
|
|
|
- **레벨 시스템**: 각 룬은 Lv.1 ~ Lv.5까지 업그레이드 가능
|
|
|
|
|
|
- **그룹 구조**: 5개 그룹으로 분류 (전투, 스킬, 장비, 보조, 모험)
|
|
|
|
|
|
- **선택 제약**: Main 그룹 1개 + Sub 그룹 1개 선택
|
|
|
|
|
|
|
|
|
|
|
|
#### 룬 ID 체계
|
|
|
|
|
|
|
|
|
|
|
|
룬 ID는 5자리 숫자로 구성됩니다:
|
|
|
|
|
|
```
|
|
|
|
|
|
XYZNN
|
|
|
|
|
|
X = 그룹 번호 (1:전투, 2:스킬, 3:장비, 4:보조, 5:모험)
|
|
|
|
|
|
Y = 라인 타입 (1:Core, 2:Sub1, 3:Sub2)
|
|
|
|
|
|
Z = 라인 내 순번
|
|
|
|
|
|
NN = 추가 식별자 (보통 01)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**예시**: `10201` = 전투 그룹(1), Sub1 라인(2), 첫 번째 룬(01)
|
|
|
|
|
|
|
|
|
|
|
|
### 5.2 룬 선택 규칙
|
|
|
|
|
|
|
|
|
|
|
|
#### 그룹 선택
|
|
|
|
|
|
|
|
|
|
|
|
1. **Main 그룹**: 5개 그룹 중 1개 선택
|
|
|
|
|
|
- Core Line, Sub 1Line, Sub 2Line 모두 선택 가능 (3개 룬)
|
|
|
|
|
|
|
|
|
|
|
|
2. **Sub 그룹**: Main이 아닌 다른 그룹 중 1개 선택
|
|
|
|
|
|
- **제약**: Core Line 선택 불가
|
|
|
|
|
|
- Sub 1Line, Sub 2Line만 선택 가능 (2개 룬)
|
|
|
|
|
|
|
|
|
|
|
|
#### 선택 예시
|
|
|
|
|
|
|
|
|
|
|
|
**Main: 전투(Battle), Sub: 스킬(Skill)**
|
|
|
|
|
|
```
|
|
|
|
|
|
선택 가능한 룬:
|
|
|
|
|
|
- 10101 (전투-Core-1)
|
|
|
|
|
|
- 10102 (전투-Core-2)
|
|
|
|
|
|
- 10103 (전투-Core-3)
|
|
|
|
|
|
- 20201 (스킬-Sub1-1)
|
|
|
|
|
|
- 20301 (스킬-Sub2-1)
|
|
|
|
|
|
|
|
|
|
|
|
총 5개 룬 장착 가능
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Main: 장비(Equipment), Sub: 보조(Assist)**
|
|
|
|
|
|
```
|
|
|
|
|
|
선택 가능한 룬:
|
|
|
|
|
|
- 30101 (장비-Core-1)
|
|
|
|
|
|
- 30102 (장비-Core-2)
|
|
|
|
|
|
- 30103 (장비-Core-3)
|
|
|
|
|
|
- 40201 (보조-Sub1-1)
|
|
|
|
|
|
- 40301 (보조-Sub2-1)
|
|
|
|
|
|
|
|
|
|
|
|
총 5개 룬 장착 가능
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 5.3 룬 그룹 및 효과
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.3.1 전투 그룹 (Battle, 10xxx)
|
|
|
|
|
|
|
|
|
|
|
|
**Core Line** (10101~10103):
|
|
|
|
|
|
|
|
|
|
|
|
| 룬 ID | 이름 | 효과 | 속성 | 레벨별 수치 |
|
|
|
|
|
|
|-------|------|------|------|-------------|
|
|
|
|
|
|
| 10101 | 충전 | 궁극기 게이지 회복량 증가 | UltimateRecoveryPer | Lv.1: +15% → Lv.5: +30% |
|
|
|
|
|
|
| 10102 | 진격 | 공격 적중 시 이동 속도 증가 | GA_Rune_10102 | 조건부 효과 (Blueprint) |
|
|
|
|
|
|
| 10103 | 공략 | 머리 공격 피해 증가 | HeadAttackDamagePer | Lv.1: +10% → Lv.5: +20% |
|
|
|
|
|
|
|
|
|
|
|
|
**Sub 1Line** (10201~10202):
|
|
|
|
|
|
|
|
|
|
|
|
| 룬 ID | 이름 | 효과 | 속성 | 레벨별 수치 |
|
|
|
|
|
|
|-------|------|------|------|-------------|
|
|
|
|
|
|
| 10201 | 분노 | 물리 피해 증가 | PhysicalDamagePer | Lv.1: +6% → Lv.5: +10% |
|
|
|
|
|
|
| 10202 | 방패 | 물리 저항 증가 | PhysicalResistancePer | Lv.1: +2% → Lv.5: +7% |
|
|
|
|
|
|
|
|
|
|
|
|
**Sub 2Line** (10301~10302):
|
|
|
|
|
|
|
|
|
|
|
|
| 룬 ID | 이름 | 효과 | 속성 | 레벨별 수치 |
|
|
|
|
|
|
|-------|------|------|------|-------------|
|
|
|
|
|
|
| 10301 | 폭풍 | 마법 피해 증가 | MagicalDamagePer | Lv.1: +6% → Lv.5: +10% |
|
|
|
|
|
|
| 10302 | 수호 | 마법 저항 증가 | MagicalResistancePer | Lv.1: +2% → Lv.5: +7% |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.3.2 스킬 그룹 (Skill, 20xxx)
|
|
|
|
|
|
|
|
|
|
|
|
**Core Line** (20101~20103):
|
|
|
|
|
|
|
|
|
|
|
|
| 룬 ID | 이름 | 효과 | 속성 | 레벨별 수치 |
|
|
|
|
|
|
|-------|------|------|------|-------------|
|
|
|
|
|
|
| 20101 | 저주 | 스킬 적중 시 지연 피해 | GA_Rune_20101 | 조건부 효과 (Blueprint) |
|
|
|
|
|
|
| 20102 | 침식 | 저주 중첩당 스킬 피해 증가 | GA_Rune_20102 | 조건부 효과 (Blueprint) |
|
|
|
|
|
|
| 20103 | 활기 | 마나 높을 때 스킬 피해 증가 | GA_Rune_20103 | 조건부 효과 (Blueprint) |
|
|
|
|
|
|
|
|
|
|
|
|
**Sub 1Line** (20201~20203):
|
|
|
|
|
|
|
|
|
|
|
|
| 룬 ID | 이름 | 효과 | 속성 | 레벨별 수치 |
|
|
|
|
|
|
|-------|------|------|------|-------------|
|
|
|
|
|
|
| 20201 | 파괴 | 스킬 피해 증가 | SkillDamagePer | Lv.1: +6% → Lv.5: +10% |
|
|
|
|
|
|
| 20202 | 왜곡 | 스킬 쿨타임 감소 | SkillCoolTimeReducePer | Lv.1: +15% → Lv.5: +25% |
|
|
|
|
|
|
| 20203 | 절약 | 스킬 마나 소모 감소 | ManaCostPer | Lv.1: -25% → Lv.5: -50% |
|
|
|
|
|
|
|
|
|
|
|
|
**Sub 2Line** (20301~20302):
|
|
|
|
|
|
|
|
|
|
|
|
| 룬 ID | 이름 | 효과 | 속성 | 레벨별 수치 |
|
|
|
|
|
|
|-------|------|------|------|-------------|
|
|
|
|
|
|
| 20301 | 명상 | 마나 회복량 증가 | MPRegenPer | Lv.1: +28% → Lv.5: +70% |
|
|
|
|
|
|
| 20302 | 영창 | 스킬 시전 속도 증가 | CastingTimePer | Lv.1: -15% → Lv.5: -30% |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.3.3 장비 그룹 (Equipment, 30xxx)
|
|
|
|
|
|
|
|
|
|
|
|
**Core Line** (30101~30103):
|
|
|
|
|
|
|
|
|
|
|
|
| 룬 ID | 이름 | 효과 | 속성 | 레벨별 수치 |
|
|
|
|
|
|
|-------|------|------|------|-------------|
|
|
|
|
|
|
| 30101 | 공허 | 비어있는 장비 슬롯당 피해 증가 | GA_Rune_30101 | Lv.1: +2%/슬롯 → Lv.5: +4%/슬롯 |
|
|
|
|
|
|
| 30102 | 견고 | 갑옷 내구도 증가 | APPer | Lv.1: +10% → Lv.5: +50% |
|
|
|
|
|
|
| 30103 | 완벽 | 장비 슬롯 다 채우면 방어력 증가 | GA_Rune_30103 | Lv.1: +7% → Lv.5: +18% |
|
|
|
|
|
|
|
|
|
|
|
|
**Sub 1Line** (30201~30202):
|
|
|
|
|
|
|
|
|
|
|
|
| 룬 ID | 이름 | 효과 | 속성 | 레벨별 수치 |
|
|
|
|
|
|
|-------|------|------|------|-------------|
|
|
|
|
|
|
| 30201 | 용사 | 검/단검/대검 피해 증가 | GA_Rune_30201 | Lv.1: +8% → Lv.5: +12% |
|
|
|
|
|
|
| 30202 | 투사 | 지팡이/활/둔기 피해 증가 | GA_Rune_30202 | Lv.1: +8% → Lv.5: +12% |
|
|
|
|
|
|
|
|
|
|
|
|
**Sub 2Line** (30301~30303):
|
|
|
|
|
|
|
|
|
|
|
|
| 룬 ID | 이름 | 효과 | 속성 | 레벨별 수치 |
|
|
|
|
|
|
|-------|------|------|------|-------------|
|
|
|
|
|
|
| 30301 | 신속 | 천 방어구당 시전 속도 증가 | GA_Rune_30301 | Lv.1: +3%/갑옷 → Lv.5: +5%/갑옷 |
|
|
|
|
|
|
| 30302 | 정밀 | 경갑 방어구당 치명타 확률 증가 | GA_Rune_30302 | Lv.1: +1%/갑옷 → Lv.5: +3%/갑옷 |
|
|
|
|
|
|
| 30303 | 강인 | 중갑 방어구당 방어력 증가 | GA_Rune_30303 | Lv.1: +1.5%/갑옷 → Lv.5: +6.5%/갑옷 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.3.4 보조 그룹 (Assist, 40xxx)
|
|
|
|
|
|
|
|
|
|
|
|
**Core Line** (40101~40102):
|
|
|
|
|
|
|
|
|
|
|
|
| 룬 ID | 이름 | 효과 | 속성 | 레벨별 수치 |
|
|
|
|
|
|
|-------|------|------|------|-------------|
|
|
|
|
|
|
| 40101 | 부활 | 쓰러진 상태에서 자동 부활 1회 | ReviveTime | Lv.1: 25초 → Lv.5: 5초 |
|
|
|
|
|
|
| 40102 | 만전 | 던전 진입 시 기본 궁극기 획득 | GA_Rune_40102 | Lv.1: 25% → Lv.5: 50% |
|
|
|
|
|
|
|
|
|
|
|
|
**Sub 1Line** (40201~40202):
|
|
|
|
|
|
|
|
|
|
|
|
| 룬 ID | 이름 | 효과 | 속성 | 레벨별 수치 |
|
|
|
|
|
|
|-------|------|------|------|-------------|
|
|
|
|
|
|
| 40201 | 면역 | 물약 사용 시 물리/마법 저항 증가 | GA_Rune_40201 | 20초간, Lv.1: +10% → Lv.5: +20% |
|
|
|
|
|
|
| 40202 | 기습 | 투척 아이템 사용 시 공격 속도 증가 | GA_Rune_40202 | 20초간, Lv.1: +10% → Lv.5: +20% |
|
|
|
|
|
|
|
|
|
|
|
|
**Sub 2Line** (40301~40302):
|
|
|
|
|
|
|
|
|
|
|
|
| 룬 ID | 이름 | 효과 | 속성 | 레벨별 수치 |
|
|
|
|
|
|
|-------|------|------|------|-------------|
|
|
|
|
|
|
| 40301 | 효율 | 물약 효과 증가 (지속 시간 제외) | PotionEffectPer | Lv.1: +25% → Lv.5: +50% |
|
|
|
|
|
|
| 40302 | 폭발 | 투척 아이템 범위 증가 | ThrowItemImpactRangePer | Lv.1: +25% → Lv.5: +50% |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.3.5 모험 그룹 (Adventure, 50xxx)
|
|
|
|
|
|
|
|
|
|
|
|
**Core Line** (50101~50103):
|
|
|
|
|
|
|
|
|
|
|
|
| 룬 ID | 이름 | 효과 | 속성 | 레벨별 수치 |
|
|
|
|
|
|
|-------|------|------|------|-------------|
|
|
|
|
|
|
| 50101 | 선물 | 잠긴 보물 상자 표시, 오픈 시 최대 HP 증가 | GA_Rune_50101 | 최대 10회, Lv.1: +11 → Lv.5: +22 |
|
|
|
|
|
|
| 50102 | 누적 | 몬스터 처치시 피해 증가 (누적) | GA_Rune_50102 | Lv.1: 1.1%/최대 11% → Lv.5: 1.5%/최대 15% |
|
|
|
|
|
|
| 50103 | 탐험 | 조명석 사용 중 지구력 소모량 감소 | GA_Rune_50103 | Lv.1: -30% → Lv.5: -60% |
|
|
|
|
|
|
|
|
|
|
|
|
**Sub 1Line** (50201~50202):
|
|
|
|
|
|
|
|
|
|
|
|
| 룬 ID | 이름 | 효과 | 속성 | 레벨별 수치 |
|
|
|
|
|
|
|-------|------|------|------|-------------|
|
|
|
|
|
|
| 50201 | 학살 | 일반 몬스터 대상 피해 증가 | NormalEnemyDamagePer | Lv.1: +20% → Lv.5: +30% |
|
|
|
|
|
|
| 50202 | 퇴치 | 엘리트 몬스터 대상 피해 증가 | EliteEnemyDamagePer | Lv.1: +16% → Lv.5: +20% |
|
|
|
|
|
|
|
|
|
|
|
|
**Sub 2Line** (50301~50303):
|
|
|
|
|
|
|
|
|
|
|
|
| 룬 ID | 이름 | 효과 | 속성 | 레벨별 수치 |
|
|
|
|
|
|
|-------|------|------|------|-------------|
|
|
|
|
|
|
| 50203 | 격퇴 | 보스 몬스터 대상 피해 증가 | BossEnemyDamagePer | Lv.1: +11% → Lv.5: +15% |
|
|
|
|
|
|
| 50301 | 기대 | 상자 열기 시간 감소 | ChestInteractionTimePer | Lv.1: -25% → Lv.5: -50% |
|
|
|
|
|
|
| 50302 | 도적 | 문 열기/닫기 시간 감소 | DoorInteractionTimePer | Lv.1: -25% → Lv.5: -50% |
|
|
|
|
|
|
| 50303 | 축복 | 석상 버프 효과 증가 | StatueEffectPer | Lv.1: +50% → Lv.5: +100% |
|
|
|
|
|
|
|
|
|
|
|
|
### 5.4 룬이 전투 로직에 미치는 영향
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.4.1 BaseDamage 계산 단계 (섹션 1.1 참조)
|
|
|
|
|
|
|
|
|
|
|
|
룬은 **3단계: 장비 효과 적용**에서 PassiveSet 속성을 통해 영향을 줍니다:
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// WSCharacterPlayer.cpp:4018-4022
|
|
|
|
|
|
// PassiveSet의 PhysicalDamagePer, MagicalDamagePer 백분율이 곱셈으로 적용
|
|
|
|
|
|
float PhysicalDamagePer = AbilitySystemComponent->GetNumericAttribute(
|
|
|
|
|
|
UPassiveSet::GetPhysicalDamagePerAttribute()) * 0.01f;
|
|
|
|
|
|
AttrValueMap[UCharacterSet::GetPhysicalDamageAttribute()] +=
|
|
|
|
|
|
AttrValueMap[UCharacterSet::GetPhysicalDamageAttribute()] * PhysicalDamagePer;
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**영향을 주는 룬**:
|
|
|
|
|
|
- **10201 분노**: PhysicalDamagePer +6~10% → 물리 공격력 증가
|
|
|
|
|
|
- **10301 폭풍**: MagicalDamagePer +6~10% → 마법 공격력 증가
|
|
|
|
|
|
- **20201 파괴**: SkillDamagePer +6~10% → 스킬 피해 증가
|
|
|
|
|
|
|
|
|
|
|
|
**예시 계산**:
|
|
|
|
|
|
```
|
|
|
|
|
|
[룬 적용 전]
|
|
|
|
|
|
캐릭터 기본 PhysicalDamage: 50
|
|
|
|
|
|
장비 옵션 증가: +30
|
|
|
|
|
|
패시브 PhysicalDamagePer: 0%
|
|
|
|
|
|
→ 최종 PhysicalDamage = (50 + 30) × 1.0 = 80
|
|
|
|
|
|
|
|
|
|
|
|
[10201 분노 Lv.5 장착 후]
|
|
|
|
|
|
캐릭터 기본 PhysicalDamage: 50
|
|
|
|
|
|
장비 옵션 증가: +30
|
|
|
|
|
|
패시브 PhysicalDamagePer: 10% (룬 효과)
|
|
|
|
|
|
→ 최종 PhysicalDamage = (50 + 30) × 1.10 = 88 (+10% 증가)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.4.2 HitBox 판정 단계 (섹션 1.2 [2] 참조)
|
|
|
|
|
|
|
|
|
|
|
|
룬은 **머리 공격 배율 계산**에 직접 영향을 줍니다:
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// WSDamageCalculation.cpp:470-510
|
|
|
|
|
|
if (HitResult->BoneName == FName(TEXT("b_Head")))
|
|
|
|
|
|
{
|
|
|
|
|
|
IsHeadShot = true;
|
|
|
|
|
|
HitBoxRate = 1.2f + HeadAttackDamagePer * 0.01f;
|
|
|
|
|
|
HitBoxRate -= 0.5f * HeadShotDamReducePer * 0.01f;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**영향을 주는 룬**:
|
|
|
|
|
|
- **10103 공략**: HeadAttackDamagePer +10~20% → 머리 공격 배율 증가
|
|
|
|
|
|
|
|
|
|
|
|
**예시 계산**:
|
|
|
|
|
|
```
|
|
|
|
|
|
[룬 적용 전]
|
|
|
|
|
|
기본 머리 배율: 1.2배
|
|
|
|
|
|
HeadAttackDamagePer: 0%
|
|
|
|
|
|
→ HitBoxRate = 1.2 + 0 = 1.2
|
|
|
|
|
|
|
|
|
|
|
|
[10103 공략 Lv.5 장착 후]
|
|
|
|
|
|
기본 머리 배율: 1.2배
|
|
|
|
|
|
HeadAttackDamagePer: 20% (룬 효과)
|
|
|
|
|
|
→ HitBoxRate = 1.2 + 0.20 = 1.4 (16.7% 추가 증가)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.4.3 저항 적용 단계 (섹션 1.2 [5] 참조)
|
|
|
|
|
|
|
|
|
|
|
|
룬은 **저항 수치**를 직접 증가시켜 받는 피해를 감소시킵니다:
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// WSDamageCalculation.cpp:543-613
|
|
|
|
|
|
// 공격 타입에 따라 적용되는 저항 결정
|
|
|
|
|
|
if (EAttackType == EWSAttackType::PhysicalSkill)
|
|
|
|
|
|
{
|
|
|
|
|
|
ResistancePer1 = PhysicalResistancePer; // 룬 10202가 영향
|
|
|
|
|
|
ResistancePer2 = ElementResistance;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (EAttackType == EWSAttackType::MagicalSkill)
|
|
|
|
|
|
{
|
|
|
|
|
|
ResistancePer1 = MagicalResistancePer; // 룬 10302가 영향
|
|
|
|
|
|
ResistancePer2 = ElementResistance;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**영향을 주는 룬**:
|
|
|
|
|
|
- **10202 방패**: PhysicalResistancePer +2~7% → 물리 피해 저항 증가
|
|
|
|
|
|
- **10302 수호**: MagicalResistancePer +2~7% → 마법 피해 저항 증가
|
|
|
|
|
|
|
|
|
|
|
|
**예시 계산**:
|
|
|
|
|
|
```
|
|
|
|
|
|
[룬 적용 전]
|
|
|
|
|
|
들어오는 물리 피해: 200
|
|
|
|
|
|
PhysicalResistancePer: 30%
|
|
|
|
|
|
→ 최종 피해 = 200 × (1 - 0.30) = 140
|
|
|
|
|
|
|
|
|
|
|
|
[10202 방패 Lv.5 장착 후]
|
|
|
|
|
|
들어오는 물리 피해: 200
|
|
|
|
|
|
PhysicalResistancePer: 37% (30% + 7% 룬 효과)
|
|
|
|
|
|
→ 최종 피해 = 200 × (1 - 0.37) = 126 (10% 추가 감소)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.4.4 최종 Damage 계산 단계 (섹션 1.2 [7] 참조)
|
|
|
|
|
|
|
|
|
|
|
|
룬은 **SkillPer 계산**에서 SkillDamagePer를 통해 영향을 줍니다:
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// WSDamageCalculation.cpp:543-613
|
|
|
|
|
|
if (EAttackType == EWSAttackType::PhysicalSkill)
|
|
|
|
|
|
{
|
|
|
|
|
|
BaseDamage = PhysicalDamage;
|
|
|
|
|
|
SkillPer = PhysicalSkillPer + SkillDamagePer; // 룬 20201이 영향
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (EAttackType == EWSAttackType::MagicalSkill)
|
|
|
|
|
|
{
|
|
|
|
|
|
BaseDamage = MagicalDamage;
|
|
|
|
|
|
SkillPer = MagicalSkillPer + SkillDamagePer; // 룬 20201이 영향
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**영향을 주는 룬**:
|
|
|
|
|
|
- **20201 파괴**: SkillDamagePer +6~10% → 모든 스킬 피해 증가
|
|
|
|
|
|
|
|
|
|
|
|
**예시 계산**:
|
|
|
|
|
|
```
|
|
|
|
|
|
[룬 적용 전]
|
|
|
|
|
|
BaseDamage: 288
|
|
|
|
|
|
SkillPer: 120% (PhysicalSkillPer만)
|
|
|
|
|
|
→ 스킬 피해 배율 = 288 × 1.20 = 345.6
|
|
|
|
|
|
|
|
|
|
|
|
[20201 파괴 Lv.5 장착 후]
|
|
|
|
|
|
BaseDamage: 288
|
|
|
|
|
|
SkillPer: 130% (PhysicalSkillPer 120% + SkillDamagePer 10%)
|
|
|
|
|
|
→ 스킬 피해 배율 = 288 × 1.30 = 374.4 (8.3% 추가 증가)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.4.5 몬스터 타입별 추가 피해 (섹션 2.3 참조)
|
|
|
|
|
|
|
|
|
|
|
|
룬은 **PassiveSet**에 몬스터 타입별 피해 증가 속성을 추가합니다:
|
|
|
|
|
|
|
|
|
|
|
|
**영향을 주는 룬**:
|
|
|
|
|
|
- **50201 학살**: NormalEnemyDamagePer +20~30%
|
|
|
|
|
|
- **50202 퇴치**: EliteEnemyDamagePer +16~20%
|
|
|
|
|
|
- **50203 격퇴**: BossEnemyDamagePer +11~15%
|
|
|
|
|
|
|
|
|
|
|
|
**적용 방식**:
|
|
|
|
|
|
이 룬들은 최종 Damage 계산 후 몬스터 타입에 따라 추가 곱셈이 적용되는 것으로 추정됩니다 (구체적인 코드 위치는 추가 확인 필요).
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
예상 공식:
|
|
|
|
|
|
최종 피해 = [기존 계산 피해] × (1 + [몬스터 타입별 피해 증가율])
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.4.6 궁극기 게이지 충전 (섹션 1.4 참조)
|
|
|
|
|
|
|
|
|
|
|
|
룬은 **UltimateRecoveryPer**를 통해 궁극기 게이지 충전 속도에 영향을 줍니다:
|
|
|
|
|
|
|
|
|
|
|
|
**영향을 주는 룬**:
|
|
|
|
|
|
- **10101 충전**: UltimateRecoveryPer +15~30%
|
|
|
|
|
|
|
|
|
|
|
|
궁극기 게이지는 피해를 주거나 힐을 할 때 충전되며, 이 룬은 충전량을 백분율로 증가시킵니다.
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.4.7 스킬 코스트 및 쿨타임 (섹션 2.3 참조)
|
|
|
|
|
|
|
|
|
|
|
|
룬은 **PassiveSet**의 스킬 관련 속성들을 수정합니다:
|
|
|
|
|
|
|
|
|
|
|
|
**영향을 주는 룬**:
|
|
|
|
|
|
- **20202 왜곡**: SkillCoolTimeReducePer +15~25% → 쿨타임 감소
|
|
|
|
|
|
- **20203 절약**: ManaCostPer -25~-50% → 마나 소모 감소
|
|
|
|
|
|
- **20302 영창**: CastingTimePer -15~-30% → 시전 시간 감소
|
|
|
|
|
|
|
|
|
|
|
|
**예시 계산 (쿨타임)**:
|
|
|
|
|
|
```
|
|
|
|
|
|
[룬 적용 전]
|
|
|
|
|
|
스킬 기본 쿨타임: 10초
|
|
|
|
|
|
SkillCoolTimeReducePer: 0%
|
|
|
|
|
|
→ 실제 쿨타임 = 10초
|
|
|
|
|
|
|
|
|
|
|
|
[20202 왜곡 Lv.5 장착 후]
|
|
|
|
|
|
스킬 기본 쿨타임: 10초
|
|
|
|
|
|
SkillCoolTimeReducePer: 25%
|
|
|
|
|
|
→ 실제 쿨타임 = 10 × (1 - 0.25) = 7.5초
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 5.5 룬 구현 메커니즘
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.5.1 직접 속성 수정 방식
|
|
|
|
|
|
|
|
|
|
|
|
대부분의 룬은 `attributeModifies` 배열을 통해 PassiveSet 또는 CharacterSet 속성을 직접 수정합니다:
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"runeSet": "10201",
|
|
|
|
|
|
"level": 5,
|
|
|
|
|
|
"runeName": "분노",
|
|
|
|
|
|
"desc": "물리 피해 {Value0}% 증가",
|
|
|
|
|
|
"descValue": [10],
|
|
|
|
|
|
"attributeModifies": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"attribute": {
|
|
|
|
|
|
"attributeName": "PhysicalDamagePer",
|
|
|
|
|
|
"attribute": "/Script/WorldStalker.PassiveSet:PhysicalDamagePer"
|
|
|
|
|
|
},
|
|
|
|
|
|
"value": 10
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
이 방식은 GAS(Gameplay Ability System)를 통해 자동으로 적용되며, 별도의 C++ 코드가 필요 없습니다.
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.5.2 Ability 기반 방식
|
|
|
|
|
|
|
|
|
|
|
|
일부 룬은 조건부 효과나 복잡한 로직이 필요하여 Blueprint Ability를 사용합니다:
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"runeSet": "10102",
|
|
|
|
|
|
"level": 1,
|
|
|
|
|
|
"runeName": "진격",
|
|
|
|
|
|
"desc": "공격 적중 시 n초간 이동 속도 {Value0}% 증가",
|
|
|
|
|
|
"descValue": [8, 2],
|
|
|
|
|
|
"attributeModifies": [],
|
|
|
|
|
|
"ability": "/Game/Blueprints/Abilities/Rune/GA_Rune_10102.GA_Rune_10102_C"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
이러한 룬들은 특정 이벤트(공격 적중, 몬스터 처치 등)에 반응하거나, 동적인 스택 시스템을 구현합니다.
|
|
|
|
|
|
|
|
|
|
|
|
**Ability 기반 룬 목록**:
|
|
|
|
|
|
- 10102 진격, 20101 저주, 20102 침식, 20103 활기
|
|
|
|
|
|
- 30101 공허, 30103 완벽, 30201 용사, 30202 투사
|
|
|
|
|
|
- 30301 신속, 30302 정밀, 30303 강인
|
|
|
|
|
|
- 40102 만전, 40201 면역, 40202 기습
|
|
|
|
|
|
- 50101 선물, 50102 누적, 50103 탐험
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.5.3 룬 데이터 조회 시스템
|
|
|
|
|
|
|
|
|
|
|
|
**코드 위치**: `WSGameplayAbility.cpp:1525-1550`
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
bool UWSGameplayAbility::GetRuneDataRowBySetID(FName RuneSetId, FRuneDataRow& OutDataRow)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 캐시된 룬 데이터 확인
|
|
|
|
|
|
if (CachedRuneDataRow)
|
|
|
|
|
|
{
|
|
|
|
|
|
OutDataRow = *CachedRuneDataRow;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// DataTable에서 룬 데이터 검색
|
|
|
|
|
|
UWSDataAsset* WSData = UWSDataAsset::GetData(GetAvatarActorFromActorInfo());
|
|
|
|
|
|
FString DataContextString = FString(TEXT("UWSGameplayAbility::GetRuneDataRowBySetID"));
|
|
|
|
|
|
TArray<FRuneDataRow*> RuneRows;
|
|
|
|
|
|
|
|
|
|
|
|
WSData->Rune->GetAllRows(DataContextString, RuneRows);
|
|
|
|
|
|
|
|
|
|
|
|
// RuneSet ID와 현재 Ability 레벨이 일치하는 룬 검색
|
|
|
|
|
|
for (FRuneDataRow* r : RuneRows)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (r->RuneSet == RuneSetId && r->Level == GetAbilityLevel())
|
|
|
|
|
|
{
|
|
|
|
|
|
CachedRuneDataRow = r;
|
|
|
|
|
|
OutDataRow = *CachedRuneDataRow;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
이 함수는 Blueprint에서 룬 데이터를 조회할 때 사용되며, 캐싱을 통해 성능을 최적화합니다.
|
|
|
|
|
|
|
|
|
|
|
|
### 5.6 룬 데이터 테이블 구조
|
|
|
|
|
|
|
|
|
|
|
|
#### DT_RuneGroup DataTable 어셋
|
|
|
|
|
|
|
|
|
|
|
|
룬 그룹의 구조와 각 라인에 포함된 룬 목록을 정의합니다:
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"RowName": "1000001",
|
|
|
|
|
|
"Data": {
|
|
|
|
|
|
"name": "전투 그룹",
|
|
|
|
|
|
"type": "Battle",
|
|
|
|
|
|
"icon": "/Game/_UI/Icon_Rune/...",
|
|
|
|
|
|
"coreLine": ["10101", "10102", "10103"],
|
|
|
|
|
|
"sub1Line": ["10201", "10202"],
|
|
|
|
|
|
"sub2Line": ["10301", "10302"]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**그룹 목록**:
|
|
|
|
|
|
1. **1000001** - 전투 (Battle): Core 3개, Sub1 2개, Sub2 2개
|
|
|
|
|
|
2. **2000001** - 스킬 (Skill): Core 3개, Sub1 3개, Sub2 2개
|
|
|
|
|
|
3. **3000001** - 장비 (Equipment): Core 3개, Sub1 2개, Sub2 3개
|
|
|
|
|
|
4. **4000001** - 보조 (Assist): Core 2개, Sub1 2개, Sub2 2개
|
|
|
|
|
|
5. **5000001** - 모험 (Adventure): Core 3개, Sub1 2개, Sub2 4개
|
|
|
|
|
|
|
|
|
|
|
|
#### DT_Rune DataTable 어셋
|
|
|
|
|
|
|
|
|
|
|
|
각 룬의 레벨별 상세 데이터를 정의합니다:
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"RowName": "1020105",
|
|
|
|
|
|
"Data": {
|
|
|
|
|
|
"runeSet": "10201",
|
|
|
|
|
|
"level": 5,
|
|
|
|
|
|
"icon": "/Game/_UI/Icon_Rune/RuneIcon_Rage.RuneIcon_Rage",
|
|
|
|
|
|
"runeName": "분노",
|
|
|
|
|
|
"desc": "물리 피해 {Value0}% 증가",
|
|
|
|
|
|
"descValue": [10],
|
|
|
|
|
|
"attributeModifies": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"attribute": {
|
|
|
|
|
|
"attributeName": "PhysicalDamagePer",
|
|
|
|
|
|
"attribute": "/Script/WorldStalker.PassiveSet:PhysicalDamagePer"
|
|
|
|
|
|
},
|
|
|
|
|
|
"value": 10
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
|
|
|
|
|
"ability": "None",
|
|
|
|
|
|
"unlockGold": 0,
|
|
|
|
|
|
"unlockSkillPoint": 20
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**주요 필드**:
|
|
|
|
|
|
- `runeSet`: 룬 ID (5자리)
|
|
|
|
|
|
- `level`: 룬 레벨 (1~5)
|
|
|
|
|
|
- `runeName`: 룬 이름
|
|
|
|
|
|
- `desc`: 설명 (UI 표시용, {Value0}, {Value1} 플레이스홀더 사용)
|
|
|
|
|
|
- `descValue`: 설명에 대입할 수치 배열
|
|
|
|
|
|
- `attributeModifies`: 직접 수정할 속성 목록
|
|
|
|
|
|
- `ability`: Blueprint Ability 경로 (복잡한 효과용)
|
|
|
|
|
|
- `unlockSkillPoint`: 해당 레벨 해금에 필요한 스킬 포인트
|
|
|
|
|
|
|
|
|
|
|
|
### 5.7 룬 시스템 활용 전략
|
|
|
|
|
|
|
|
|
|
|
|
#### 공격력 극대화 빌드
|
|
|
|
|
|
|
|
|
|
|
|
**목표**: BaseDamage와 스킬 피해를 최대한 증가
|
|
|
|
|
|
|
|
|
|
|
|
**Main: 스킬 그룹**
|
|
|
|
|
|
- 20101 저주 (조건부 피해)
|
|
|
|
|
|
- 20201 파괴 (+10% 스킬 피해)
|
|
|
|
|
|
- 20301 명상 (+70% 마나 회복)
|
|
|
|
|
|
|
|
|
|
|
|
**Sub: 전투 그룹**
|
|
|
|
|
|
- 10201 분노 (+10% 물리 피해) 또는 10301 폭풍 (+10% 마법 피해)
|
|
|
|
|
|
- 10103 공략 (+20% 머리 공격)
|
|
|
|
|
|
|
|
|
|
|
|
**효과**: 스킬 피해 +10%, 물리/마법 피해 +10%, 머리 공격 +20%
|
|
|
|
|
|
|
|
|
|
|
|
#### 생존력 극대화 빌드
|
|
|
|
|
|
|
|
|
|
|
|
**Main: 전투 그룹**
|
|
|
|
|
|
- 10101 충전 (+30% 궁극기 회복)
|
|
|
|
|
|
- 10202 방패 (+7% 물리 저항)
|
|
|
|
|
|
- 10302 수호 (+7% 마법 저항)
|
|
|
|
|
|
|
|
|
|
|
|
**Sub: 보조 그룹**
|
|
|
|
|
|
- 40201 면역 (물약 사용 시 저항 +20%)
|
|
|
|
|
|
- 40301 효율 (물약 효과 +50%)
|
|
|
|
|
|
|
|
|
|
|
|
**효과**: 저항 대폭 증가, 물약 효율 극대화, 궁극기 빠른 충전
|
|
|
|
|
|
|
|
|
|
|
|
#### 스킬 연타 빌드
|
|
|
|
|
|
|
|
|
|
|
|
**Main: 스킬 그룹**
|
|
|
|
|
|
- 20201 파괴 (+10% 스킬 피해)
|
|
|
|
|
|
- 20202 왜곡 (+25% 쿨타임 감소)
|
|
|
|
|
|
- 20203 절약 (-50% 마나 소모)
|
|
|
|
|
|
|
|
|
|
|
|
**Sub: 스킬 그룹 Sub2**
|
|
|
|
|
|
- 20301 명상 (+70% 마나 회복)
|
|
|
|
|
|
- 20302 영창 (+30% 시전 속도)
|
|
|
|
|
|
|
|
|
|
|
|
**효과**: 쿨타임 -25%, 마나 소모 -50%, 마나 회복 +70%, 시전 속도 +30%
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
**룬 시스템 핵심 요약**:
|
|
|
|
|
|
1. 5개 그룹 × 3개 라인으로 구성된 38개 룬 세트
|
|
|
|
|
|
2. Main(3룬) + Sub(2룬)으로 총 5개 룬 장착
|
|
|
|
|
|
3. 직접 속성 수정 또는 Ability를 통한 조건부 효과
|
|
|
|
|
|
4. 전투 로직의 여러 단계에 직접적인 영향
|
|
|
|
|
|
5. BaseDamage, 저항, 스킬 코스트 등 핵심 수치 조정
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 6. 전투 관련 코드 목록
|
|
|
|
|
|
|
|
|
|
|
|
### 6.1 데미지 계산 시스템
|
|
|
|
|
|
|
|
|
|
|
|
#### WSDamageCalculation.cpp (1238라인)
|
|
|
|
|
|
|
|
|
|
|
|
**역할**: 모든 일반 공격 및 스킬 데미지 계산의 핵심 로직 실행
|
|
|
|
|
|
|
|
|
|
|
|
**주요 함수**:
|
|
|
|
|
|
- `Execute_Implementation` (라인 251-1238): 전체 11단계 계산 흐름 제어
|
|
|
|
|
|
- `DamageStatics()`: Attribute 캡처 정의
|
|
|
|
|
|
|
|
|
|
|
|
**주요 계산 단계별 코드 위치**:
|
|
|
|
|
|
|
|
|
|
|
|
1. **BaseDamage 계산**:
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// 라인 316-322: Level 배율 적용
|
|
|
|
|
|
PhysicalDamage = PhysicalDamage * Level;
|
|
|
|
|
|
MagicalDamage = MagicalDamage * Level;
|
|
|
|
|
|
|
|
|
|
|
|
// 라인 543-613: 공격 타입별 BaseDamage 결정
|
|
|
|
|
|
if (EAttackType == EWSAttackType::Normal)
|
|
|
|
|
|
BaseDamage = PhysicalDamage;
|
|
|
|
|
|
else if (EAttackType == EWSAttackType::PhysicalSkill)
|
|
|
|
|
|
BaseDamage = PhysicalDamage;
|
|
|
|
|
|
else if (EAttackType == EWSAttackType::MagicalSkill)
|
|
|
|
|
|
BaseDamage = MagicalDamage;
|
|
|
|
|
|
|
|
|
|
|
|
// 라인 620-685: 던전 룰 배율
|
|
|
|
|
|
switch (DungeonRule) {
|
|
|
|
|
|
case EDungeonRule::EnemyAtkUp: BaseDamage *= 1.4f; break;
|
|
|
|
|
|
// ...
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. **HitBox 판정** (라인 470-510):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
IsFrontAttack = UWSAbilityBlueprintLibrary::IsFrontAttack(EffectCauser, Target, bUseOwnerRotation);
|
|
|
|
|
|
if (HitResult->BoneName == FName(TEXT("b_Head")))
|
|
|
|
|
|
{
|
|
|
|
|
|
IsHeadShot = true;
|
|
|
|
|
|
HitBoxRate = 1.2f + HeadAttackDamagePer * 0.01f;
|
|
|
|
|
|
HitBoxRate -= 0.5f * HeadShotDamReducePer * 0.01f;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
3. **치명타 판정** (라인 512-527):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
if (bUseCritical && FMath::FRandRange(0.0f, 100.0f) < CriticalPer)
|
|
|
|
|
|
{
|
|
|
|
|
|
isCritical = true;
|
|
|
|
|
|
CriticalDamageRate = (CriticalDamagePer * 0.01f) + (FMath::Rand() * CriticalDamageRange);
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
4. **저항 및 최종 피해** (라인 706-718):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
ResistancePer1 = FMath::Min(ResistancePer1, 75.0f);
|
|
|
|
|
|
ResistancePer2 = FMath::Min(ResistancePer2, 75.0f);
|
|
|
|
|
|
|
|
|
|
|
|
Damage = Floor(BaseDamage * HitBoxRate * (SkillPer * 0.01) *
|
|
|
|
|
|
((1 - ResistancePer1 * 0.01) * (1 - ResistancePer2 * 0.01) * (1 - DamageReductionPer * 0.01)) *
|
|
|
|
|
|
CriticalDamageRate * (1 - TakeDamageReductionPer * 0.01) * (1 + TakeDamageIncreasePer * 0.01));
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
5. **Shield/Armor/HP 적용** (라인 883-1047):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// Shield 먼저 소모
|
|
|
|
|
|
ShieldDamage = Clamp(DamageNoResist, 0, Shield);
|
|
|
|
|
|
if (Shield > 0) {
|
|
|
|
|
|
Damage = Clamp(Damage - ShieldDamage, 0, Damage);
|
|
|
|
|
|
Shield -= ShieldDamage;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Armor Gating
|
|
|
|
|
|
if (Armor / ArmorMax > 0.5) {
|
|
|
|
|
|
DamageGating = (Armor - Damage) - (ArmorMax * 0.5);
|
|
|
|
|
|
if (DamageGating < 0) Damage += DamageGating;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**참조 섹션**: 1.2 일반 공격/스킬 데미지 계산 흐름
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### WSHealCalculation.cpp (126라인)
|
|
|
|
|
|
|
|
|
|
|
|
**역할**: 힐 스킬의 회복량 계산
|
|
|
|
|
|
|
|
|
|
|
|
**주요 함수**:
|
|
|
|
|
|
- `Execute_Implementation` (라인 49-125): 힐 계산 및 적용
|
|
|
|
|
|
|
|
|
|
|
|
**힐 계산 공식** (라인 95-98):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
float HealMagnitude = InComingHeal * Level;
|
|
|
|
|
|
// 힐 = 기본 힐량 + (마법공격력 × 스킬 계수) × (인트배율)
|
|
|
|
|
|
HealMagnitude = HealMagnitude + (MagicalDamage * (1.0f + (SkillDamagePer * 0.01f))) * (MagicalSkillPer * 0.01f);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**과치유 방지** (라인 106-108):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
float TargetMaxHP = TargetASC->GetNumericAttribute(UCharacterSet::GetHPMaxAttribute());
|
|
|
|
|
|
float TargetHP = TargetASC->GetNumericAttribute(UCharacterSet::GetHPAttribute());
|
|
|
|
|
|
float HealAmount = FMath::Min(HealMagnitude, TargetMaxHP - TargetHP);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**힐 무효 처리** (라인 110-113):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
if (TargetASC->HasMatchingGameplayTag(FGameplayTag::RequestGameplayTag("Effect.IgnoreHeal")))
|
|
|
|
|
|
{
|
|
|
|
|
|
HealAmount = 0.0f;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**궁극기 게이지 충전** (라인 118-123):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
if (!SourceASC->HasMatchingGameplayTag(FGameplayTag::RequestGameplayTag("Ability.Ultimate")))
|
|
|
|
|
|
{
|
|
|
|
|
|
InstigatorCharacter->CharacterSet->SetUltimateCurrentValue(
|
|
|
|
|
|
FMath::Min(HealAmount + UltimateCurrentvalue, UltimateMaxValue));
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**참조 섹션**: 1.4 힐 계산
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 6.2 속성 세트 (Attribute Sets)
|
|
|
|
|
|
|
|
|
|
|
|
#### WSAttributeSet.h
|
|
|
|
|
|
|
|
|
|
|
|
**역할**: 모든 Attribute Set의 베이스 클래스
|
|
|
|
|
|
|
|
|
|
|
|
**주요 기능**:
|
|
|
|
|
|
- Gameplay Attribute 시스템의 기본 구조 제공
|
|
|
|
|
|
- Replication 설정
|
|
|
|
|
|
- Attribute 변경 감지 및 클램핑
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### PrimarySet.h
|
|
|
|
|
|
|
|
|
|
|
|
**역할**: 1차 스탯 (Str, Dex, Int, Con, Wis) 정의
|
|
|
|
|
|
|
|
|
|
|
|
**속성**:
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Str)
|
|
|
|
|
|
float Str = 0; // 힘
|
|
|
|
|
|
|
|
|
|
|
|
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Dex)
|
|
|
|
|
|
float Dex = 0; // 민첩
|
|
|
|
|
|
|
|
|
|
|
|
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Int)
|
|
|
|
|
|
float Int = 0; // 지능
|
|
|
|
|
|
|
|
|
|
|
|
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Con)
|
|
|
|
|
|
float Con = 0; // 체질
|
|
|
|
|
|
|
|
|
|
|
|
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Wis)
|
|
|
|
|
|
float Wis = 0; // 지혜
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**특징**:
|
|
|
|
|
|
- 총합 75 제한
|
|
|
|
|
|
- 커브 테이블을 통해 2차 스탯 피해율로 변환
|
|
|
|
|
|
- 장비, 패시브 스킬로 추가 증가 가능
|
|
|
|
|
|
|
|
|
|
|
|
**참조 섹션**: 2.1 1차 스탯
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### CharacterSet.h
|
|
|
|
|
|
|
|
|
|
|
|
**역할**: 2차 스탯 (HP, Damage, Defense, Resistance 등) 정의
|
|
|
|
|
|
|
|
|
|
|
|
**주요 속성 그룹**:
|
|
|
|
|
|
1. **기본 스탯**: HP, MP, Stamina, Shield
|
|
|
|
|
|
2. **피해**: PhysicalDamage, MagicalDamage, 각종 피해율
|
|
|
|
|
|
3. **방어**: Defense, Armor, 저항
|
|
|
|
|
|
4. **특수**: Breakdown, Ultimate, Critical
|
|
|
|
|
|
|
|
|
|
|
|
**초기화** (CharacterSet.cpp:8-82):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
void UCharacterSet::InitData(FCharacterStatData Data, UPrimarySet* PrimarySet, UPassiveSet* PassiveSet, bool HasAuthority)
|
|
|
|
|
|
{
|
|
|
|
|
|
SetPhysicalDamage(Data.PhysicalDamage);
|
|
|
|
|
|
SetMagicalDamage(Data.MagicalDamage);
|
|
|
|
|
|
SetDefense(Data.Defense);
|
|
|
|
|
|
// ...
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**참조 섹션**: 2.2 2차 스탯
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### PassiveSet.h (490라인)
|
|
|
|
|
|
|
|
|
|
|
|
**역할**: 패시브 스탯 (백분율 수정자) 정의
|
|
|
|
|
|
|
|
|
|
|
|
**속성 구성**:
|
|
|
|
|
|
- **공통 패시브** (라인 125-260): 36개 속성
|
|
|
|
|
|
- 피해 증가율 (PhysicalDamagePer, MagicalDamagePer 등)
|
|
|
|
|
|
- 방어/속도/HP/MP 증가율
|
|
|
|
|
|
- 스킬 코스트/쿨다운 감소율
|
|
|
|
|
|
- 인터랙션 시간 조정
|
|
|
|
|
|
|
|
|
|
|
|
- **캐릭터별 전용 퍽** (라인 263-461):
|
|
|
|
|
|
- Hilda: 7개 전용 퍽
|
|
|
|
|
|
- Urud: 6개 전용 퍽
|
|
|
|
|
|
- Nave: 10개 전용 퍽
|
|
|
|
|
|
- Baran: 8개 전용 퍽
|
|
|
|
|
|
- Rio: 8개 전용 퍽
|
|
|
|
|
|
- Clad: 5개 전용 퍽
|
|
|
|
|
|
|
|
|
|
|
|
- **범용 퍽 슬롯** (라인 466-488): Perk1~Perk8
|
|
|
|
|
|
|
|
|
|
|
|
**적용 방식**:
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// WSCharacterPlayer.cpp:4018-4022
|
|
|
|
|
|
float PhysicalDamagePer = AbilitySystemComponent->GetNumericAttribute(
|
|
|
|
|
|
UPassiveSet::GetPhysicalDamagePerAttribute()) * 0.01f;
|
|
|
|
|
|
AttrValueMap[UCharacterSet::GetPhysicalDamageAttribute()] +=
|
|
|
|
|
|
AttrValueMap[UCharacterSet::GetPhysicalDamageAttribute()] * PhysicalDamagePer;
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**참조 섹션**: 2.3 패시브 스탯
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### EnemySet.h
|
|
|
|
|
|
|
|
|
|
|
|
**역할**: 몬스터 전용 스탯 정의
|
|
|
|
|
|
|
|
|
|
|
|
**주요 속성**:
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_CombinationArmor)
|
|
|
|
|
|
float CombinationArmor = 0; // 몬스터 전용 콤비네이션 아머
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**특징**:
|
|
|
|
|
|
- 몬스터에게만 적용되는 특수 속성
|
|
|
|
|
|
- CombinationArmor: 다중 부위 아머 시스템
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 6.3 캐릭터 시스템
|
|
|
|
|
|
|
|
|
|
|
|
#### WSCharacterBase.cpp/h
|
|
|
|
|
|
|
|
|
|
|
|
**역할**: 플레이어와 적 캐릭터의 공통 베이스 클래스
|
|
|
|
|
|
|
|
|
|
|
|
**주요 기능**:
|
|
|
|
|
|
|
|
|
|
|
|
1. **Ability System 초기화**:
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
void AWSCharacterBase::InitializeAbilitySystem()
|
|
|
|
|
|
{
|
|
|
|
|
|
AbilitySystemComponent->InitAbilityActorInfo(this, this);
|
|
|
|
|
|
PrimarySet->InitData(*StatDataRow);
|
|
|
|
|
|
CharacterSet->InitData(*StatDataRow, PrimarySet, PassiveSet, HasAuthority());
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. **반죽음 판정** (WSCharacterBase.h:178-180):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
bool CanHalfDie() const
|
|
|
|
|
|
{
|
|
|
|
|
|
// 파티원이 있고 생존한 파티원이 있을 때만 반죽음 가능
|
|
|
|
|
|
return HasPartyMembers() && HasAlivePartyMembers();
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
3. **Hit Reaction 처리**:
|
|
|
|
|
|
- 피격 모션 재생
|
|
|
|
|
|
- 넉백/스턴 처리
|
|
|
|
|
|
- Breakdown 게이지 증가
|
|
|
|
|
|
|
|
|
|
|
|
**참조 섹션**: 4.3 반죽음
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### WSCharacterPlayer.cpp/h
|
|
|
|
|
|
|
|
|
|
|
|
**역할**: 플레이어 캐릭터 전용 로직
|
|
|
|
|
|
|
|
|
|
|
|
**주요 기능**:
|
|
|
|
|
|
|
|
|
|
|
|
1. **1차 스탯 → 2차 스탯 변환** (라인 3214-3245):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
void AWSCharacterPlayer::UpdatePrimaryStats()
|
|
|
|
|
|
{
|
|
|
|
|
|
FRealCurve* NormalDamagePerCurve = WSData->PrimaryStat->FindSimpleCurve(FName(TEXT("NormalDamagePer")), DataContextString);
|
|
|
|
|
|
CharacterSet->SetNormalDamagePer(NormalDamagePerCurve->Eval(PrimarySet->GetStr()));
|
|
|
|
|
|
|
|
|
|
|
|
FRealCurve* PhysicalSkillPerCurve = WSData->PrimaryStat->FindSimpleCurve(FName(TEXT("PhysicalSkillPer")), DataContextString);
|
|
|
|
|
|
CharacterSet->SetPhysicalSkillPer(PhysicalSkillPerCurve->Eval(PrimarySet->GetStr()));
|
|
|
|
|
|
|
|
|
|
|
|
FRealCurve* MagicalSkillPerCurve = WSData->PrimaryStat->FindSimpleCurve(FName(TEXT("MagicalSkillPer")), DataContextString);
|
|
|
|
|
|
CharacterSet->SetMagicalSkillPer(MagicalSkillPerCurve->Eval(PrimarySet->GetInt()));
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. **장비 효과 적용** (라인 3566-3860):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
void AWSCharacterPlayer::GiveEquip(FEquipItemData* EquipItem, int CacheIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 장비 랜덤 옵션 적용
|
|
|
|
|
|
AttrValueMap.Add(UCharacterSet::GetPhysicalDamageAttribute(),
|
|
|
|
|
|
FItemHelper::CalculateOption(EquipItem, EItemOption::PhysicalDamageInc));
|
|
|
|
|
|
|
|
|
|
|
|
// 패시브 스탯 백분율 적용
|
|
|
|
|
|
float PhysicalDamagePer = AbilitySystemComponent->GetNumericAttribute(
|
|
|
|
|
|
UPassiveSet::GetPhysicalDamagePerAttribute()) * 0.01f;
|
|
|
|
|
|
AttrValueMap[UCharacterSet::GetPhysicalDamageAttribute()] +=
|
|
|
|
|
|
AttrValueMap[UCharacterSet::GetPhysicalDamageAttribute()] * PhysicalDamagePer;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
3. **스킬/패시브 관리**:
|
|
|
|
|
|
- 스킬 슬롯 관리
|
|
|
|
|
|
- 패시브 스킬 활성화
|
|
|
|
|
|
- 퍽 시스템 적용
|
|
|
|
|
|
|
|
|
|
|
|
**참조 섹션**: 1.1 BaseDamage 계산 과정
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### WSCharacterEnemy.cpp/h
|
|
|
|
|
|
|
|
|
|
|
|
**역할**: 적 캐릭터 전용 로직
|
|
|
|
|
|
|
|
|
|
|
|
**주요 기능**:
|
|
|
|
|
|
- AI 연동
|
|
|
|
|
|
- Breakdown 시스템
|
|
|
|
|
|
- 몬스터 등급별 스탯 조정
|
|
|
|
|
|
- CombinationArmor 처리
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 6.4 스킬 데이터 구조
|
|
|
|
|
|
|
|
|
|
|
|
#### SkillDataRow.h
|
|
|
|
|
|
|
|
|
|
|
|
**역할**: 스킬 데이터 테이블 구조 정의
|
|
|
|
|
|
|
|
|
|
|
|
**주요 열거형**:
|
|
|
|
|
|
|
|
|
|
|
|
1. **공격 타입** (라인 13-21):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
UENUM(BlueprintType)
|
|
|
|
|
|
enum class EWSAttackType : uint8
|
|
|
|
|
|
{
|
|
|
|
|
|
Normal = 0, // 일반 공격
|
|
|
|
|
|
PhysicalSkill = 1, // 물리 스킬
|
|
|
|
|
|
MagicalSkill = 2, // 마법 스킬
|
|
|
|
|
|
FixedSkill = 3, // 고정 스킬 (저항 무시)
|
|
|
|
|
|
None = 4
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. **원소 타입** (라인 24-33):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
UENUM(BlueprintType)
|
|
|
|
|
|
enum class EWSElementType : uint8
|
|
|
|
|
|
{
|
|
|
|
|
|
None = 0,
|
|
|
|
|
|
Fire = 1, // 화염
|
|
|
|
|
|
Poison = 2, // 독
|
|
|
|
|
|
Water = 3, // 물
|
|
|
|
|
|
Lightning = 4, // 번개
|
|
|
|
|
|
Holy = 5, // 빛
|
|
|
|
|
|
Dark = 6 // 암흑
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**스킬 데이터 구조**:
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
USTRUCT(BlueprintType)
|
|
|
|
|
|
struct FSkillDataRow : public FTableRowBase
|
|
|
|
|
|
{
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
|
|
|
|
|
float BaseDamage; // 기본 피해량
|
|
|
|
|
|
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
|
|
|
|
|
EWSAttackType AttackType; // 공격 타입
|
|
|
|
|
|
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
|
|
|
|
|
EWSElementType ElementType; // 원소 타입
|
|
|
|
|
|
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
|
|
|
|
|
float ManaCost; // 마나 소비
|
|
|
|
|
|
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
|
|
|
|
|
float CooldownTime; // 쿨다운 시간
|
|
|
|
|
|
|
|
|
|
|
|
// ... 기타 스킬 속성
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**참조 섹션**: 3.1 공격 타입, 3.2 원소 타입
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 6.5 발사체 시스템
|
|
|
|
|
|
|
|
|
|
|
|
#### WSProjectileBase.cpp/h
|
|
|
|
|
|
|
|
|
|
|
|
**역할**: 화살, 마법 투사체 등 원거리 공격 구현
|
|
|
|
|
|
|
|
|
|
|
|
**주요 기능**:
|
|
|
|
|
|
1. 투사체 물리 시뮬레이션
|
|
|
|
|
|
2. 충돌 감지 및 히트 판정
|
|
|
|
|
|
3. 관통, 폭발 등 특수 효과
|
|
|
|
|
|
4. RangedType 설정
|
|
|
|
|
|
|
|
|
|
|
|
**히트 처리**:
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
void AWSProjectileBase::OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor,
|
|
|
|
|
|
UPrimitiveComponent* OtherComp, FVector NormalImpulse,
|
|
|
|
|
|
const FHitResult& Hit)
|
|
|
|
|
|
{
|
|
|
|
|
|
// RangedType = true 설정
|
|
|
|
|
|
// GameplayEffect 적용 (WSDamageCalculation 호출)
|
|
|
|
|
|
// RangedResistancePer 저항 적용됨
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**참조 섹션**: 3.2 원거리 타입
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 6.6 기타 데이터 구조
|
|
|
|
|
|
|
|
|
|
|
|
#### CharacterStatDataRow.h
|
|
|
|
|
|
|
|
|
|
|
|
**역할**: 캐릭터 기본 스탯 DataTable 구조
|
|
|
|
|
|
|
|
|
|
|
|
**주요 필드** (라인 63-198):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
USTRUCT(BlueprintType)
|
|
|
|
|
|
struct FCharacterStatData : public FTableRowBase
|
|
|
|
|
|
{
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
|
|
|
|
|
float Str = 0; // 1차 스탯
|
|
|
|
|
|
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
|
|
|
|
|
float PhysicalDamage = 0; // 캐릭터 기본 공격력
|
|
|
|
|
|
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
|
|
|
|
|
float MagicalDamage = 0; // 캐릭터 기본 마법 공격력
|
|
|
|
|
|
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
|
|
|
|
|
float Defense = 0; // 캐릭터 기본 방어력
|
|
|
|
|
|
|
|
|
|
|
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
|
|
|
|
|
float BreakdownMax = -1.0f; // 브레이크다운 최대치
|
|
|
|
|
|
|
|
|
|
|
|
// ... 기타 기본 스탯
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**사용 위치**:
|
|
|
|
|
|
- `WSCharacterPlayer::InitializeAbilitySystem` (라인 1059)
|
|
|
|
|
|
- `PrimarySet::InitData`
|
|
|
|
|
|
- `CharacterSet::InitData`
|
|
|
|
|
|
|
|
|
|
|
|
**참조 섹션**: 1.1 BaseDamage 계산 과정 (1단계)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### DataTable.json
|
|
|
|
|
|
|
|
|
|
|
|
**역할**: 언리얼 에디터의 DataTable 어셋을 JSON 형식으로 익스포트한 파일
|
|
|
|
|
|
|
|
|
|
|
|
> **참고**: 이 파일은 "Asset Export to JSON" 에디터 확장 기능을 통해 생성된 결과물입니다.
|
|
|
|
|
|
> 언리얼 엔진의 DataTable 어셋(DT_Rune, DT_RuneGroup 등)을 LLM이 분석할 수 있도록 텍스트 기반 JSON 형식으로 변환한 것입니다.
|
|
|
|
|
|
|
|
|
|
|
|
**룬 시스템 관련 DataTable 어셋**:
|
|
|
|
|
|
- **DT_RuneGroup**: 5개 룬 그룹 구조 정의
|
|
|
|
|
|
- Core Line, Sub 1Line, Sub 2Line 구성
|
|
|
|
|
|
- 각 그룹별 선택 가능 룬 목록
|
|
|
|
|
|
|
|
|
|
|
|
- **DT_Rune**: 38개 룬 세트의 레벨별 데이터
|
|
|
|
|
|
- 룬 ID (runeSet), 레벨 (1~5)
|
|
|
|
|
|
- 효과 설명 (desc, descValue)
|
|
|
|
|
|
- 직접 속성 수정 (attributeModifies) 또는 Ability 참조
|
|
|
|
|
|
- 해금 조건 (unlockSkillPoint)
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"runeSet": "10201",
|
|
|
|
|
|
"level": 5,
|
|
|
|
|
|
"runeName": "분노",
|
|
|
|
|
|
"desc": "물리 피해 {Value0}% 증가",
|
|
|
|
|
|
"descValue": [10],
|
|
|
|
|
|
"attributeModifies": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"attribute": {
|
|
|
|
|
|
"attributeName": "PhysicalDamagePer",
|
|
|
|
|
|
"attribute": "/Script/WorldStalker.PassiveSet:PhysicalDamagePer"
|
|
|
|
|
|
},
|
|
|
|
|
|
"value": 10
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**참조 섹션**: 5.6 룬 데이터 테이블 구조
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### WSGameplayAbility.h/cpp
|
|
|
|
|
|
|
|
|
|
|
|
**역할**: Gameplay Ability 베이스 클래스, **룬 데이터 조회 기능 포함**
|
|
|
|
|
|
|
|
|
|
|
|
**룬 관련 함수** (WSGameplayAbility.h:209, 268):
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// 룬 데이터 조회 함수
|
|
|
|
|
|
UFUNCTION(BlueprintCallable, Category = "WorldStalker")
|
|
|
|
|
|
bool GetRuneDataRowBySetID(FName RuneSetId, FRuneDataRow& OutDataRow);
|
|
|
|
|
|
|
|
|
|
|
|
// 룬 데이터 캐시
|
|
|
|
|
|
FRuneDataRow* CachedRuneDataRow;
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**구현** (WSGameplayAbility.cpp:1525-1550):
|
|
|
|
|
|
- RuneSet ID와 Ability 레벨로 룬 데이터 검색
|
|
|
|
|
|
- 캐싱을 통한 성능 최적화
|
|
|
|
|
|
- Blueprint에서 룬 효과 적용 시 사용
|
|
|
|
|
|
|
|
|
|
|
|
**참조 섹션**: 5.5.3 룬 데이터 조회 시스템
|