#!/usr/bin/env python3 """Projectile 노티파이 조사 스크립트""" import json from pathlib import Path from collections import defaultdict # AnimMontage.json 로드 montage_file = Path("D:/Work/WorldStalker/DS-전투분석_저장소/원본데이터/AnimMontage.json") with open(montage_file, 'r', encoding='utf-8') as f: montage_data = json.load(f) # validated_data.json 로드 (유틸리티 스킬 확인용) val_file = Path("D:/Work/WorldStalker/DS-전투분석_저장소/분석결과/20251024_210822_v2/validated_data.json") with open(val_file, 'r', encoding='utf-8') as f: val_data = json.load(f) print("=" * 80) print("Projectile 노티파이 조사") print("=" * 80) # 1. 우르드 다발 화살 몽타주 확인 print("\n=== 예시: Urud 다발 화살 (SK110205) ===") assets = montage_data.get('Assets', []) multi_arrow = [a for a in assets if a.get('AssetName') == 'AM_PC_Urud_Base_B_Skill_MultiArrow'] if multi_arrow: m = multi_arrow[0] notifies = m.get('AnimNotifies', []) print(f"Montage: {m.get('AssetName')}") print(f"Total notifies: {len(notifies)}") print("\nNotify Classes:") for n in notifies: notify_class = n.get('NotifyClass', 'N/A') notify_state = n.get('NotifyStateClass', 'N/A') if notify_class != 'N/A': print(f" - NotifyClass: {notify_class}") if notify_state != 'N/A': print(f" - NotifyStateClass: {notify_state}") else: print("몽타주를 찾을 수 없음!") # 2. 모든 PC 스킬 몽타주에서 Projectile 관련 노티파이 패턴 수집 print("\n" + "=" * 80) print("모든 PC 스킬 몽타주에서 Projectile 패턴 조사") print("=" * 80) projectile_patterns = defaultdict(int) pc_skill_montages = [a for a in assets if 'PC' in a.get('AssetPath', '') and 'Skill' in a.get('AssetPath', '')] print(f"\n총 PC 스킬 몽타주: {len(pc_skill_montages)}개") for montage in pc_skill_montages: notifies = montage.get('AnimNotifies', []) for notify in notifies: notify_class = notify.get('NotifyClass', '') notify_state = notify.get('NotifyStateClass', '') # Projectile 또는 관련 키워드 포함 keywords = ['Projectile', 'projectile', 'Shot', 'shot', 'Fire', 'Spawn', 'Arrow', 'Bullet'] for keyword in keywords: if keyword in notify_class: projectile_patterns[notify_class] += 1 if keyword in notify_state: projectile_patterns[notify_state] += 1 print(f"\nProjectile 관련 노티파이 패턴 발견: {len(projectile_patterns)}개") for pattern, count in sorted(projectile_patterns.items(), key=lambda x: x[1], reverse=True): print(f" {pattern}: {count}회") # 3. 유틸리티로 판정된 스킬 중 Projectile 노티파이가 있는 스킬 찾기 print("\n" + "=" * 80) print("유틸리티 판정 스킬 중 Projectile 노티파이 보유 스킬") print("=" * 80) utility_with_projectile = [] for stalker_id, stalker_data in val_data.items(): skills = stalker_data.get('skills', {}) for skill_id, skill in skills.items(): is_utility = skill.get('isUtility', False) if is_utility: # 몽타주 데이터 확인 montage_data_list = skill.get('montageData', []) for montage_info in montage_data_list: all_notifies = montage_info.get('allNotifies', []) has_projectile = False projectile_notifies = [] for notify in all_notifies: notify_class = notify.get('NotifyClass', '') notify_state = notify.get('NotifyStateClass', '') for keyword in keywords: if keyword in notify_class or keyword in notify_state: has_projectile = True projectile_notifies.append(notify_class or notify_state) if has_projectile: utility_with_projectile.append({ 'stalker': stalker_id, 'skillId': skill_id, 'skillName': skill.get('name', 'N/A'), 'montage': montage_info.get('assetName', 'N/A'), 'projectileNotifies': projectile_notifies, 'damageRate': skill.get('skillDamageRate', 0) }) print(f"\n유틸리티로 잘못 판정된 가능성이 있는 스킬: {len(utility_with_projectile)}개\n") for item in utility_with_projectile: print(f"[{item['stalker']}] {item['skillId']} - {item['skillName']}") print(f" Damage Rate: {item['damageRate']}") print(f" Montage: {item['montage']}") print(f" Projectile Notifies: {', '.join(set(item['projectileNotifies']))}") print() # 4. 권장 ATTACK_NOTIFY_CLASSES 업데이트 print("=" * 80) print("권장 ATTACK_NOTIFY_CLASSES 추가 키워드") print("=" * 80) # 빈도가 높은 패턴 추출 (5회 이상) high_frequency = [p for p, c in projectile_patterns.items() if c >= 3] print("\n추가 권장 키워드 (빈도 3회 이상):") for pattern in high_frequency[:10]: print(f" - '{pattern.split('_')[-1] if '_' in pattern else pattern}'")