- **슬롯 1~3 = 클래스 일치 행**: 근접 4클래스는 `ClassConfig.n_AcquiredSkill1~3` 에 각각 Active 3행만 갖는다(실측 · `table_skilllist.cs:257` 의 클래스 스킬 목록도 JobPassive 를 제외해 3행). 그래서 슬롯 1~3 은 이 3행이 전부이고, **선택압은 슬롯 4에만 걸린다**.
-`n_SkillClassID` 는 **0 그대로 둔다**(바꾼 필드 최소화 · 다른 클래스 재사용 여지 유지). 대신 아래 §5 ①의 부작용을 참고할 것.
- **자동/수동 규칙 = 코드 0 으로 이미 충족**: `PCActor.Update` 자동 분기만 `t_autoskill <= 0f` 를 조건에 걸고 발동 후 `t_autoskill = Random.Range(2f, 3f)` 로 재장전한다(= 자동 2~3 s 유지). 수동 경로에는 이 게이트가 없어 **수동 = 즉시**. 데이터로 바꿀 것이 없다.
### 1-2. ⚠ 적용 전 반드시 같이 바꿔야 하는 선행 값 (이 초안 범위 밖 · 원본 파일이라 손대지 않음)
`Actor.cs:733-741` 에 `needMP > 현재 MP` 면 스킬이 **불발**(`return false`)하는 게이트가 있다. 그런데 실측 MP 풀은 **100 이 아니라 30**:
| 값 | 현행(실측) | 기준서 §B 전제 | 조치 |
|---|---|---|---|
| `GlobalValue.MP` | **30** | MP **100** 기준 | 100 으로 올리지 않으면 **슬롯 4(40 MP)는 영구 불발** · 슬롯 3(25)도 만탱일 때만 발동 |
| `ClassConfig.n_DefaultMP` (12행 전부) | **30** | 100 | 위와 동일 |
| `GlobalValue.MP_REGEN` | **3** | 5 %/s = 100 기준 초당 **5** | 5 로 상향 |
→ **이 3개를 함께 반영하지 않으면 프리셋은 리듬을 만들지 못한다.** 813c(패드) 착수 전 Lead 결정 필요.
---
## 2. 811i 이펙트 매핑 입력 열 (차지 / 본체 / 착탄)
- 후보는 전부 `Assets/Res_Addr/Effect/**`**실존 프리팹명**(하위 폴더 포함 303개 중 선택 · 실존 grep **불일치 0건**).
- 클래스 원소는 각 행의 `e_SkillExtraType` → `SkillTypeConfig.e_SkillEffect` 로 확인(상태 이펙트는 이미 테이블이 재생하므로 아래 표에서 제외).
- 811i 설계안 §B-3 `vfxSlots` = `{phase Charge/Body/Impact, prefab, anchor, scale}` 의 **prefab 열 입력값**으로 그대로 쓰면 된다.
| 클래스 | 슬롯 | SkillID | charge | body | impact | 상태 이펙트(SkillTypeConfig 자동) |
| 700012 | 10308 | 없음 | JobPassive | 행복한 유대 | `ClassConfig(10601 twohand).n_ExtraSkill` | 〃 | **보류** · 10601 로 정정 |
**세션 3 로그의 "런타임 도달 불가 → 조치 불필요" 판단을 정정한다.**
근거: `MyValue.Set_JobPassive`(`MyValue.cs:497`)가 `job.n_ExtraSkill` 로 이 6행을 **매 클래스 세팅마다 실제로 읽어**`e_SkillEnhance` · `f_ExtraValue*` 를 스탯에 반영한다. 즉 **행 자체는 살아 있는 경로**이고, 도달 불가인 것은 `n_SkillClassID` **열 값 하나뿐**이다.
- 삭제하면 6개 클래스의 직업 패시브 스탯이 통째로 사라진다 → **삭제 불가**.
-`n_SkillClassID` 는 JobPassive 조회 경로에서 안 읽히므로(`table_skilllist.cs:257` 이 JobPassive 를 제외 · `Actor.cs:700` 게이트는 `Use_Skill` 전용) **지금 당장의 버그는 아니다**. 우선순위 = 낮음, 위험 = 낮음, 조치 = **xlsm 열 값 정정만**.
- 참고(별건): 같은 열 오류가 살아 있는 클래스에도 1건 있다 — **`700002`(마검사 직업 패시브)의 `n_SkillClassID` 가 `10201`(bladedancer)** 인데 실제 참조처는 `ClassConfig(10102 spellblade).n_ExtraSkill` 이다. 정정 대상에 함께 올릴 것을 권고.
---
## 4. 적용 절차 (butler.xlsm SOT → Export)
> ⚠ **xlsm 동기화 필요.** `Assets/ResWork/Table/Export/*.json` 은 **산출물**이고 SOT 는 `Assets/ResWork/Table/butler.xlsm` 이다. Export JSON 만 고치면 다음 표 추출 때 **되돌아간다**.
1.**결정**: §1-2 의 MP 풀(30 → 100) · MP_REGEN(3 → 5) 을 Lead/PD 가 확정한다. 미확정이면 여기서 멈춘다(슬롯 3·4 가 불발이라 검증이 무의미).
2.**xlsm 편집**: `butler.xlsm` 의 `SkillList` 시트에서 위 표 16행의 **`f_CoolTime` · `n_MP` 두 열만** 수정. 다른 열·다른 행은 건드리지 않는다.
- 같은 파일의 `GlobalValue` 시트에서 `MP` · `MP_REGEN`, `ClassConfig` 시트에서 `n_DefaultMP` 를 1번 결정대로 수정.
- (선택) §3 의 `n_SkillClassID` 7건(고아 6 + 700002) 정정.
3.**Export 재생성**: 기존 표 추출 경로로 `SkillList.json` · `GlobalValue.json` · `ClassConfig.json` 재출력. 인코딩은 **UTF-8 BOM · 단일 라인 · 전 값 문자열** 을 유지할 것(이 초안 파일이 같은 규격이니 diff 로 대조하면 된다).
4.**서버 열 확인 「미확인」**: `Assets/Editor/GetServerTables.cs:19` 의 SkillList 서버 열 목록에 **`n_MP` · `f_CoolTime` 이 포함**되어 있다 → 이 두 값은 서버 테이블로도 나간다. 클라 단독 반영이 서버 값에 덮이는지는 서버 쪽을 못 봐서 확인 못 했다. **반영 전 서버 담당 확인 필요.**
5.**슬롯 장착**: 실제 4슬롯은 `ServerClass.Get_EquipSkillID(slot)` = `Equip.Skill[Preset][slot]` 에서 온다(`ServerClass.cs:456`). 이 초안은 **어떤 스킬이 어느 슬롯에 와야 하는지**를 정의할 뿐이고, **장착 자체는 서버 프리셋(또는 신규 클래스 기본 장착 데이터)** 이 해야 한다 → 813c 착수 시 같이 처리.
6.**초안 파일 정리**: 본 표 반영이 끝나면 `_WL813n_SkillList.json` 은 역할이 끝난다(게임 미참조). 삭제 여부는 Lead 판단.
-`arr_magicMaxCoolTime[i]` 는 `PCActor.cs:190-191` 에서 `f_CoolTime` 에 `COOLTIME_Multiplier` 를 적용해 세팅(`table_skilllist.cs:211` `Get_CoolTime`). `GlobalValue.COOLTIME_Multiplier` 실측 = **0** → 감쇄 없음 → **표 값이 그대로 쿨**이다.
- **판정 기준**: 4슬롯 쿨 링이 각각 6 / 8 / 12 / 20 s 주기로 차오르고, 자동 발동 간격이 2~3 s 로 유지되면 성공. 슬롯 4가 20 s 마다 한 번만 터지는지 로그로 확인(813m `SkillCast` 카운트).
- **주의**: 자동 발동에는 `Vector3.Distance(...) <= f_SkillRange` 조건이 붙는다(`PCActor.cs:93`). 슬롯 4의 `f_SkillRange = 10` 은 근접 클래스 교전 거리(`ClassConfig.f_AttackRange` 1.5)보다 훨씬 넓어 사거리로는 막히지 않는다.
**③ 회귀 체크**: 원본 `SkillList.json` 은 **바이트 무변경**(123,125 bytes) — 이 초안은 게임이 읽지 않는 새 파일이므로 반영 전까지 런타임 영향 0.
- **반영 후(xlsm 편집 뒤)**: 되돌릴 값은 **`f_CoolTime = 5` · `n_MP = 5`**(16행 전부 동일하므로 일괄 복구 가능) + `GlobalValue.MP = 30` · `MP_REGEN = 3` · `ClassConfig.n_DefaultMP = 30`(12행). xlsm 은 git 이력에서 이전 리비전을 꺼내고 Export 를 재생성하는 것이 가장 안전하다.
- 813c 패드가 이미 붙은 뒤라면 데이터만 되돌려도 패드는 그대로 동작한다(패드는 슬롯 값을 읽기만 한다).
---
## 7. 미확인 (에디터·서버 없이 확인 불가)
1. 서버가 `n_MP` · `f_CoolTime` 을 덮어쓰는지(`GetServerTables.cs:19` 서버 열 목록에 포함) — **서버 담당 확인 필요**.
2. 슬롯 4 후보(702005/702006/702009/702012)의 **실제 타격 범위·명중 수**. 기준서 §B "광역 반경 2.5~4 m · 1발 ≥3마리" 충족 여부는 Play 로만 판정 가능(`Skill_*` 프리팹은 `Res_Addr/Skill/`·`Res_Addr/Projectile/` 에 실존 확인까지만 함).
-`ClassConfig` 는 **근접 4클래스만** 상향했다. 나머지 8행(10201·10202·10301~10303·10401·10402·10601)은 **`"30"` 그대로** — 이 4클래스만 813n 프리셋 대상이라 다른 클래스의 밸런스를 건드리지 않기 위함. **비근접 8클래스는 여전히 §1-2 의 MP 불일치 상태**이며, 그 클래스로 4슬롯을 확장할 때 함께 올려야 한다.
- 이로써 슬롯 4(40 MP)·슬롯 3(25 MP)가 `Actor.cs:733-741` MP 게이트를 통과한다(풀 100 · 초당 5 회복 = 슬롯 4 재충전 8 s <쿨20s).
### 8-3. 검증 (python `utf-8-sig` · git)
| 항목 | 결과 | 방법 |
|---|---|---|
| 초안 델타 = `{f_CoolTime, n_MP}` 뿐 | **True** (16행 전수 · 델타 필드 합집합 2개) | 초안 vs 원본 35필드 전 셀 비교 |
| 재직렬화 왕복 무손실 | **3파일 전부 byte-identical** | `json.dumps(ensure_ascii=False, separators=(', ', ': '))` == 원문 (변경 전 사전 확인) |
| 행 수 · 필드 수 · 키 순서 · 전 값 str · BOM | **전부 불변** | `[list(r.keys()) for r in data]` 리스트 동일성 + `isinstance(v, str)` 전수 |
| 변경 셀 수 | **39 / 2 / 4 = 45** (의도치와 정확히 일치) | `git show HEAD:<path>` vs 현행 파일 셀 단위 비교 |
| 변경 필드 종류 | SkillList 3종(`f_CoolTime`·`n_MP`·`n_SkillClassID`) · 그 외 32필드 무변경 | 동일 스크립트 |
| 변경 파일 범위 | `git status --porcelain` = **M 3건만** | 허용 3파일 + 본 문서 외 수정 0 |
| 컴파일 게이트 | **미실행(해당 없음)** | 코드 0 · `unity` 명령 0회 |