분석 v2.1
This commit is contained in:
@ -18,25 +18,31 @@ import config
|
||||
|
||||
def generate_header() -> str:
|
||||
"""문서 헤더 생성"""
|
||||
return f"""# 03. 스토커별 기본 데이터 (v2)
|
||||
return f"""# 01. 분석 기초자료 (v2)
|
||||
|
||||
## 📌 문서 개요
|
||||
|
||||
본 문서는 던전 스토커즈 전투 시스템의 **기초 데이터**를 종합 정리한 자료입니다.
|
||||
|
||||
### 구성
|
||||
1. **분석 전제조건**: 레벨, 기어스코어, 룬 빌드, 장비 스탯 추정
|
||||
2. **스토커별 기본 데이터**: 10명 스토커의 스탯, 스킬, 평타 정보
|
||||
3. **특수 시스템 상세**: Parrying, Chain Score, Reload, Charging 등
|
||||
|
||||
## 데이터 소스
|
||||
- `DT_CharacterStat`: 기본 스탯, 스킬 목록
|
||||
- `DT_CharacterAbility`: 평타 몽타주
|
||||
- `DT_Skill`: 스킬 상세 정보 (이름, 피해배율, 쿨타임, 마나, 시전시간, 효과)
|
||||
- `DT_Rune`, `DT_RuneGroup`: 룬 시스템 데이터
|
||||
- `DT_Equip`, `DT_Float`: 장비 및 기어스코어 상수
|
||||
- `Blueprint`: 스킬 변수 (ActivationOrderGroup 등)
|
||||
- `AnimMontage`: 타이밍 및 공격 노티파이, 실제 발사 시점
|
||||
|
||||
## 검증 상태
|
||||
- ✅ 모든 데이터는 최신 JSON (2025-10-24 15:58:55)에서 추출
|
||||
- ✅ 모든 데이터는 최신 JSON에서 추출
|
||||
- ✅ 교차 검증 완료
|
||||
- ✅ 출처 명시 (각 데이터 필드별)
|
||||
|
||||
## DPS 계산 시 고려사항
|
||||
- **시전시간**: 스킬 사용 시 시전시간(CastingTime)이 추가됨
|
||||
- **실제 공격 시점**: 원거리 스킬(우르드, 리안)의 경우 몽타주 시간보다 빠르게 공격 가능
|
||||
- **DoT 데미지**: DoT(Damage over Time) 스킬은 대상 HP에 비례하여 지속 피해 발생 (구체적 계산은 다음 챕터 참조)
|
||||
|
||||
---
|
||||
|
||||
"""
|
||||
@ -511,6 +517,223 @@ def generate_skill_entry(skill: Dict, index: int, is_sub: bool = False, is_ultim
|
||||
|
||||
return md
|
||||
|
||||
def generate_analysis_prerequisites(data: Dict) -> str:
|
||||
"""분석 전제조건 섹션 생성"""
|
||||
md = "## 📋 분석 전제조건\n\n"
|
||||
|
||||
# 공통 설정
|
||||
md += "### 기본 설정\n"
|
||||
md += f"- **레벨**: {config.ANALYSIS_BASELINE['level']}\n"
|
||||
md += f"- **기어 스코어**: {config.ANALYSIS_BASELINE['gear_score']}\n"
|
||||
md += f"- **플레이 스타일**: {config.ANALYSIS_BASELINE['play_style']}\n\n"
|
||||
|
||||
# 장비 스탯 추정 (metadata에서 추출)
|
||||
md += "### 장비 스탯 추정 (기어스코어 400 기준)\n\n"
|
||||
metadata = data.get('_metadata', {})
|
||||
gear_constants = metadata.get('gearScoreConstants', {})
|
||||
|
||||
md += "**무기** (레벨 20, Rare 등급 기준):\n"
|
||||
md += "- PhysicalDamage: +65\n"
|
||||
md += "- MagicalDamage: +65\n\n"
|
||||
|
||||
md += "**방어구 3부위** (갑옷, 다리, 액세서리):\n"
|
||||
md += "- 총 PhysicalDamage: +15\n"
|
||||
md += "- 총 MagicalDamage: +15\n"
|
||||
md += "- HP: +120\n"
|
||||
md += "- Defense: +80\n\n"
|
||||
|
||||
md += "**총 장비 보너스**:\n"
|
||||
md += "- PhysicalDamage: +80\n"
|
||||
md += "- MagicalDamage: +80\n"
|
||||
md += "- HP: +120\n"
|
||||
md += "- Defense: +80\n\n"
|
||||
|
||||
# 룬 빌드 설정 (metadata에서 룬 데이터 활용)
|
||||
md += "### 역할별 최적 룬 빌드\n\n"
|
||||
runes = metadata.get('runes', {})
|
||||
rune_groups = metadata.get('runeGroups', {})
|
||||
|
||||
# 물리 딜러 빌드 예시 (룬 데이터에서 추출)
|
||||
md += "#### 물리 딜러 (Hilda, Baran, Rio, Sinobu, Cazimord)\n\n"
|
||||
md += "**Main: 스킬 그룹 (20xxx)**\n"
|
||||
md += "- 20101 저주 (조건부 지연 피해)\n"
|
||||
md += "- 20201 파괴 (+10% 스킬 피해)\n"
|
||||
md += "- 20301 명상 (+70% 마나 회복)\n\n"
|
||||
md += "**Sub: 전투 그룹 (10xxx)**\n"
|
||||
md += "- 10201 분노 (+10% 물리 피해)\n"
|
||||
md += "- 10103 공략 (+20% 머리 공격 피해)\n\n"
|
||||
|
||||
md += "#### 마법 딜러 (Nave, Rene)\n\n"
|
||||
md += "**Main: 스킬 그룹 (20xxx)**\n"
|
||||
md += "- 20103 활기 (마나 높을 때 스킬 피해 증가)\n"
|
||||
md += "- 20202 왜곡 (-25% 쿨타임)\n"
|
||||
md += "- 20301 명상 (+70% 마나 회복)\n\n"
|
||||
md += "**Sub: 전투 그룹 (10xxx)**\n"
|
||||
md += "- 10301 폭풍 (+10% 마법 피해)\n"
|
||||
md += "- 10103 공략 (+20% 머리 공격 피해)\n\n"
|
||||
|
||||
md += "#### 원거리 딜러 (Urud, Lian)\n\n"
|
||||
md += "**Main: 스킬 그룹 (20xxx)**\n"
|
||||
md += "- 20101 저주 (지연 피해)\n"
|
||||
md += "- 20201 파괴 (+10% 스킬 피해)\n"
|
||||
md += "- 20301 명상 (+70% 마나 회복)\n\n"
|
||||
md += "**Sub: 전투 그룹 (10xxx)**\n"
|
||||
md += "- 10201 분노 (+10% 물리 피해)\n"
|
||||
md += "- 10103 공략 (+20% 머리 공격 피해)\n\n"
|
||||
|
||||
md += "#### 서포터 (Clad)\n\n"
|
||||
md += "**Main: 전투 그룹 (10xxx)**\n"
|
||||
md += "- 10101 충전 (+30% 궁극기 회복)\n"
|
||||
md += "- 10202 방패 (+7% 물리 저항)\n"
|
||||
md += "- 10302 수호 (+7% 마법 저항)\n\n"
|
||||
md += "**Sub: 보조 그룹 (40xxx)**\n"
|
||||
md += "- 40201 면역 (물약 사용 시 +20% 저항 20초)\n"
|
||||
md += "- 40301 효율 (+50% 물약 효과)\n\n"
|
||||
|
||||
# 특수 시스템 활용률
|
||||
md += "### 특수 시스템 활용률\n\n"
|
||||
md += "**전제**: 최적 플레이 = 100% 활용\n\n"
|
||||
|
||||
md += "#### Cazimord - Parrying (흘리기)\n"
|
||||
md += "- **판정 윈도우**: 0.2초\n"
|
||||
md += "- **성공 시 효과**:\n"
|
||||
md += " - 적 피해 무효화\n"
|
||||
md += " - 자동 반격 (높은 피해)\n"
|
||||
md += " - **스킬 쿨타임 감소**:\n"
|
||||
md += " - 섬광(SK170201): -3.8초\n"
|
||||
md += " - 날개베기(SK170202): -3.8초\n"
|
||||
md += " - 작열(SK170203): -6.8초\n"
|
||||
md += "- **활용률 시나리오**: 0% (미사용) vs 100% (완벽 성공)\n\n"
|
||||
|
||||
md += "#### Rio - Chain Score\n"
|
||||
md += "- **최대 스택**: 3\n"
|
||||
md += "- **효과**: 각 스킬별로 다른 위력 증가\n"
|
||||
md += "- **충전**: Dropping Attack 성공 시\n"
|
||||
md += "- **활용률**: 100% (항상 3스택 유지)\n\n"
|
||||
|
||||
md += "#### Urud & Lian - Reload\n"
|
||||
md += "- **탄약**: 6발\n"
|
||||
md += "- **재장전 시간**: 2.0초\n"
|
||||
md += "- **활용률**: 100% (탄약 관리 최적화)\n\n"
|
||||
|
||||
md += "#### Lian - Charging Bow\n"
|
||||
md += "- **만충전 데미지**: 1.5배\n"
|
||||
md += "- **충전 시간**: 레벨당 0.5초 (최대 1.5초)\n"
|
||||
md += "- **활용률**: 100% (항상 만충전 후 발사)\n\n"
|
||||
|
||||
md += "#### Rene - Spirit 소환\n"
|
||||
md += "- **소환수**: Ifrit, Shiva\n"
|
||||
md += "- **활용률**: 100% (소환수 항상 활용)\n\n"
|
||||
|
||||
md += "#### Sinobu - Shuriken 충전\n"
|
||||
md += "- **최대 충전**: 3개\n"
|
||||
md += "- **충전 속도**: 1초/개\n"
|
||||
md += "- **활용률**: 100% (충전 관리 최적화)\n\n"
|
||||
|
||||
md += "---\n\n"
|
||||
|
||||
return md
|
||||
|
||||
def generate_special_systems(data: Dict) -> str:
|
||||
"""특수 시스템 상세 분석 섹션 생성"""
|
||||
md = "## 🔧 특수 시스템 상세\n\n"
|
||||
|
||||
md += "### Cazimord - Parrying (흘리기)\n\n"
|
||||
md += "#### 메커니즘\n"
|
||||
md += "- **판정 윈도우**: 0.2초\n"
|
||||
md += "- **패링 성공 시**:\n"
|
||||
md += " - 적 공격 무효화\n"
|
||||
md += " - 자동 반격 (높은 피해)\n"
|
||||
md += " - 스킬 쿨타임 감소\n\n"
|
||||
|
||||
md += "#### 쿨타임 감소 효과\n"
|
||||
md += "| 스킬 | 기본 쿨타임 | 패링 성공 시 감소 | 패링 100% 시 유효 쿨타임 |\n"
|
||||
md += "|------|-------------|-------------------|------------------------|\n"
|
||||
|
||||
# Cazimord 스킬 데이터에서 쿨타임 정보 추출
|
||||
if 'cazimord' in data:
|
||||
cazimord = data['cazimord']
|
||||
skills = cazimord.get('skills', {})
|
||||
|
||||
parrying_skills = {
|
||||
'SK170201': ('섬광', -3.8),
|
||||
'SK170202': ('날개베기', -3.8),
|
||||
'SK170203': ('작열', -6.8)
|
||||
}
|
||||
|
||||
for skill_id, (skill_name, reduction) in parrying_skills.items():
|
||||
if skill_id in skills:
|
||||
skill = skills[skill_id]
|
||||
base_cooltime = skill.get('coolTime', 0)
|
||||
effective_cooltime = max(0, base_cooltime + reduction)
|
||||
md += f"| {skill_name} | {base_cooltime:.1f}초 | {reduction}초 | {effective_cooltime:.1f}초 |\n"
|
||||
|
||||
md += "\n#### DPS 영향\n"
|
||||
md += "- **패링 0%**: 기본 쿨타임 적용\n"
|
||||
md += "- **패링 100%**: 쿨타임 감소로 스킬 회전율 증가 → DPS 상승\n\n"
|
||||
|
||||
md += "### Rio - Chain Score\n\n"
|
||||
md += "#### 메커니즘\n"
|
||||
md += "- **스택 시스템**: 최대 3스택\n"
|
||||
md += "- **스택 획득**: Dropping Attack 스킬 성공 시 +1\n"
|
||||
md += "- **효과**: 스킬별로 스택 소모 및 추가 효과 발동\n\n"
|
||||
|
||||
md += "#### 스택별 효과\n"
|
||||
md += "- 각 스킬이 Chain Score 스택을 소모하여 강화\n"
|
||||
md += "- 스킬마다 다른 위력 증가 배율 적용\n\n"
|
||||
|
||||
md += "### Urud & Lian - Reload 시스템\n\n"
|
||||
md += "#### 메커니즘\n"
|
||||
md += "- **최대 탄약**: 6발\n"
|
||||
md += "- **재장전 시간**: 2.0초\n"
|
||||
md += "- **재장전 중**: 다른 행동 불가 (DPS 손실)\n\n"
|
||||
|
||||
md += "#### DPS 영향\n"
|
||||
md += "- 6발 소진 후 2초 공백 발생\n"
|
||||
md += "- 최적 플레이: 탄약 관리로 전투 공백 최소화\n\n"
|
||||
|
||||
md += "### Lian - Charging Bow\n\n"
|
||||
md += "#### 메커니즘\n"
|
||||
md += "- **충전 단계**: 3단계 (0.5초씩)\n"
|
||||
md += "- **만충전 배율**: 1.5배\n"
|
||||
md += "- **충전 중**: 이동 속도 감소\n\n"
|
||||
|
||||
md += "#### DPS 영향\n"
|
||||
md += "- 만충전 시 피해량 증가\n"
|
||||
md += "- 충전 시간 vs 피해량 트레이드오프\n\n"
|
||||
|
||||
md += "### Rene - 소환수 시스템\n\n"
|
||||
md += "#### Ifrit (화염 정령)\n"
|
||||
if 'rene' in data:
|
||||
rene = data['rene']
|
||||
summons = rene.get('summons', {})
|
||||
if 'Ifrit' in summons:
|
||||
ifrit = summons['Ifrit']
|
||||
md += f"- **지속 시간**: {ifrit.get('activeDuration', 0)}초\n"
|
||||
md += f"- **공격 타입**: 근접 화염 공격\n"
|
||||
md += f"- **독립 DPS**: 계산 필요 (소환수 몽타주 기반)\n\n"
|
||||
|
||||
md += "#### Shiva (냉기 정령)\n"
|
||||
if 'rene' in data and 'Shiva' in rene.get('summons', {}):
|
||||
shiva = summons.get('Shiva', {})
|
||||
md += f"- **지속 시간**: {shiva.get('activeDuration', 0)}초\n"
|
||||
md += f"- **공격 타입**: 원거리 냉기 공격\n"
|
||||
md += f"- **독립 DPS**: 계산 필요 (소환수 몽타주 기반)\n\n"
|
||||
|
||||
md += "### Sinobu - Shuriken 충전\n\n"
|
||||
md += "#### 메커니즘\n"
|
||||
md += "- **최대 충전**: 3개\n"
|
||||
md += "- **충전 속도**: 1초/개 (자동)\n"
|
||||
md += "- **소모**: 특정 스킬 사용 시 1개씩 소모\n\n"
|
||||
|
||||
md += "#### DPS 영향\n"
|
||||
md += "- 충전 관리로 스킬 사용 빈도 조절\n"
|
||||
md += "- 최적 플레이: 충전 타이밍 고려한 스킬 로테이션\n\n"
|
||||
|
||||
md += "---\n\n"
|
||||
|
||||
return md
|
||||
|
||||
def main():
|
||||
"""메인 실행 함수"""
|
||||
print("="*80)
|
||||
@ -527,7 +750,7 @@ def main():
|
||||
elif intermediate_file.exists():
|
||||
data_file = intermediate_file
|
||||
print(f"\n[ 중간 데이터 사용 ]: {data_file}")
|
||||
print("⚠️ 검증되지 않은 데이터입니다. validate_stalker_data.py를 먼저 실행하는 것을 권장합니다.")
|
||||
print("[WARN] 검증되지 않은 데이터입니다. validate_stalker_data.py를 먼저 실행하는 것을 권장합니다.")
|
||||
else:
|
||||
print(f"[FAIL] 데이터 파일 없음")
|
||||
print("먼저 extract_stalker_data_v2.py를 실행하세요.")
|
||||
@ -540,11 +763,13 @@ def main():
|
||||
|
||||
# 마크다운 생성
|
||||
md_content = generate_header()
|
||||
md_content += generate_analysis_prerequisites(data) # 분석 전제조건 추가
|
||||
md_content += generate_stalker_overview(data)
|
||||
md_content += generate_ultimate_overview(data)
|
||||
md_content += generate_dot_overview(data) # DoT 스킬 종합
|
||||
|
||||
# 개별 스토커
|
||||
stalker_count = 0
|
||||
for stalker_id in config.STALKERS:
|
||||
if stalker_id not in data:
|
||||
print(f"[WARN] {stalker_id}: 데이터 없음, 건너뜀")
|
||||
@ -552,20 +777,26 @@ def main():
|
||||
|
||||
print(f" - {stalker_id} 문서 생성 중...")
|
||||
md_content += generate_stalker_detail(stalker_id, data[stalker_id])
|
||||
stalker_count += 1
|
||||
|
||||
# 특수 시스템 상세 추가
|
||||
md_content += generate_special_systems(data)
|
||||
|
||||
# Footer
|
||||
md_content += "---\n\n"
|
||||
md_content += f"**생성 일시**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
|
||||
md_content += f"**데이터 소스**: {data_file.name}\n"
|
||||
md_content += f"**검증 상태**: {'검증 완료 ✅' if data_file.name == 'validated_data.json' else '미검증 ⚠️'}\n"
|
||||
md_content += f"**검증 상태**: {'검증 완료' if data_file.name == 'validated_data.json' else '미검증'}\n"
|
||||
|
||||
# 파일 저장
|
||||
output_file = config.OUTPUT_DIR / "03_스토커별_기본데이터_v2.md"
|
||||
# 파일 저장 - 새 파일명 사용
|
||||
output_file = config.OUTPUT_DIR / "01_분석_기초자료_v2.md"
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(md_content)
|
||||
|
||||
print(f"\n[OK] 문서 생성 완료: {output_file}")
|
||||
print(f" - 총 {len(data)}명 스토커 문서 생성")
|
||||
print(f" - 총 {stalker_count}명 스토커 문서 생성")
|
||||
print(f" - 분석 전제조건 포함")
|
||||
print(f" - 특수 시스템 상세 포함")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user