Project_WL/Assets/WL/Settings/WL813e_ZoneApply.md

110 lines
9.1 KiB
Markdown
Raw Normal View History

# WL-813e — 군중 존 5개 + 보스 아레나(Anubis) 데이터 적용 기록
> 발주 WL-813e (PD #813 · 트랙 S) · 브랜치 `wl/systems/WL-813e-zones-boss` (base `wl/systems/WL-813b-boss-content` @ `a4a053c44`)
> 규격 = 813b 완료보고 §6 + 초안 2건(`_WL813b_MonsterAppear_Draft.json` · `_WL813b_BossArena_Draft.json`) + 핵앤슬래시 기준서 v1 §B 요소 1·6 · §D-1 813e 행
> **코드 변경 0** — `Assets/Script/**` 무수정. 보스 프리팹(`Res_Addr/Mobs/FieldBoss/Anubis.prefab`) 인스펙터 값 무수정(813h 가 테이블화).
## 🔴 SOT — xlsm 동기화 필요
데이터 SOT 는 **butler.xlsm (PD 소유)** 다. 아래 6행은 `MonsterAppear.json` 에 직접 추가했으므로,
**xlsm 의 MonsterAppear 시트에 같은 6행을 넣고 재익스포트하기 전까지는 다음 익스포트에서 사라진다.**
`WL_Nature.prefab` 의 스포너 재바인딩(1~5 → 813001~813005)도 같이 살아 있어야 짝이 맞는다.
## 1. 반영한 것 (전수)
### (a) `Assets/ResWork/Table/Export/MonsterAppear.json` — 새 행 6개 (기존 46행 **바이트 무변경**)
| SpawnerID | 존 | Lv | ATK | DEF/MDEF | HP | s_AppearMonster | e_SpawnerType | 리젠 s | 최대 | 순찰 | Exp/Gold |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 813001 | 존1 첫 교전 | 1 | 10 | 0 | 300 | 101\|102\|103\|104 (Batty 4 · scale 1.5) | Random | 1.5 | 12 | 8 | 10/1 |
| 813002 | 존2 밀집 최대 | 2 | 12 | 0 | 450 | 168~172 (Porin 5 · scale 1.3) | Random | 1.2 | 15 | 8 | 15/2 |
| 813003 | 존3 혼합 | 3 | 14 | 0 | 600 | 173\|174\|175\|146\|147\|151 (Racco 3 + Rabby 3) | Random | 1.2 | 14 | 8 | 20/3 |
| 813004 | 존4 웨이브 관문 | 4 | 16 | 0 | 800 | 118\|119\|120 (Devilu 3) | PhaseAllKill | 2.0 | 8 | 6 | 30/4 |
| 813005 | 존5 엘리트 | 5 | 20 | 0 | 1500 | 1014\|1015\|1016 (Golem Elite 3 · scale 2.5) | Order | 3.0 | 5 | 6 | 60/8 |
| 813010 | 보스 아레나 | 6 | 18 | 0 | **450** | 10006 (Anubis) | Random | 60 | 1 | 4 | 500/100 |
- `n_DropReward` 는 6행 모두 기존 백 `9700001`(전 스포너 공용). 새 백은 813f 소관.
- **813010 만 초안 값에서 바꿨다**: 초안 행은 `n_MonsterHP 1200`(실 HP 20×1200 = 24,000 ≈ 240s)인데
초안 자신의 `_계산` 과 기준서 §B 요소6(보스 **60~120 s** · 첫 보스 90 s 목표)에 어긋난다.
→ 존1 의 3 s 처치(HP 300)가 함의하는 DPS 100 으로 역산: `450 = 90 s × 100 / f_BaseHPRate 20`**실 HP 9,000**.
ATK 18 은 초안대로(실 ATK 30×18 = 540). 플레이어 무적 유지 중이라 ATK 는 아직 체감에 영향이 없다.
### (b) `Assets/Res_Addr/Map/WL_Nature.prefab` — 6줄 변경 + 새 노드 1기 (총 +86 / 5 줄)
| 무엇 | 변경 |
|---|---|
| `WL_Nature/maplv/1~5``MobControlMgr.SpawnerID` | 1·2·3·4·5 → **813001~813005** (각 1줄) |
| `WL_Nature` 루트 Transform `m_Children` | FieldBoss 컨테이너 1줄 추가 |
| `WL_Nature/FieldBoss/1` (신규) | GameObject 2 + Transform 2 + `FieldBossData` 1 = YAML 문서 5개(80줄) |
`FieldBossData` 값: `n_MonsterID 10006` · `n_SpawnerId 813010` · `RegenTime 60` · **`isChapterBoss 0`** · pos **(139, 0.8, 20)**
- **`isChapterBoss` 는 반드시 0.** WL_Nature 의 `MapData.m_ChapterPortal` 이 null 이라 1이면 `AfterDie` 에서 NullReference (`FieldBossData.cs:47-49`) — 실측 확인.
- 스포너 ID 6~19 와 다른 12개 맵(WL_Nature02~10 · WL_Start · Map_C01/02)은 **손대지 않았다**(ID 1~19 는 13개 맵 공용 · 813b 교훈).
## 2. 실측 (헤드리스 에디터 · `AgentScripts/WL813e_Zones.cs`)
| 항목 | 값 |
|---|---|
| 새 행 인식 | **6 / 6** |
| 스포너 → 행 연결 | **19 / 19** (미연결 0 = `MobActor.cs:62` null 로 인한 NullReference 자리 0) |
| 새 존 재바인딩 | **5 / 5** |
| 몹 프리팹 자산 누락 | **0** (존 21종 + 보스 1종 전부 `Res_Addr/Mobs` 에 실존) |
| FieldBossData | **1기** · MonsterList 행 O · `Res_Addr/Mobs/FieldBoss/Anubis.prefab` O · MonsterAppear 행 O |
| 보스 실 스탯 | 실 HP = 20 × 450 = **9,000** · 실 ATK = 30 × 18 = **540** (`MyValue.cs:370-371`) |
| 동시 생존 · 풀 | **179마리 · 366개** (813b 기준 175 · 375 → 생존 +4 · 인스턴스 9) |
| NavMesh 도달성 | 스포너 19 + 보스 1 = **PathComplete 20 / 20** · PathPartial 0 |
| 컴파일 게이트 | PASS · `error CS` 0 · 콘솔 error **0** |
### 🔴 아레나 좌표를 초안에서 옮긴 이유 (813b 미확인 ③ 해소)
초안 후보A **(137, 0.6, 22)** 는 NavMesh 위(스냅 0.33 m)이긴 하나
**플레이어 시작 지점(`Portal_Start` 115,0,10)에서 `NavMesh.CalculatePath` = `PathPartial`** 이다 — 끊긴 구역이다.
같은 스윕에서 스포너 원점 19개는 전부 `PathComplete` 였으므로 프로브 문제가 아니다.
→ 후보A 주변 ±16 m 를 2 m 격자로 훑어 «시작에서 PathComplete + 모든 스포너 원점에서 15 m 이상» 을 만족하는 92개 중
**후보A 에서 가장 가까운 (139, 0.8, 20)** 을 채택했다(후보A 로부터 **2.8 m** · 경로장 38.4 m · 스냅 0.01 m · 최근접 스포너 20.1 m).
초안의 설계 의도(SP1·SP4 사이 · 시작에서 약 38 m · 군집 반경 10 밖)는 그대로 유지된다.
### 미확인
- **Play 실측(절두체 내 몹 수 · 처치 간격 · 보스 스폰 시각 · fps) = 「미확인」.**
이 worktree 헤드리스 에디터에서 `Assets/Resources/PlayFabSharedSettings.asset` 이 임포트되지 않아
(`Resources.LoadAll<PlayFabSharedSettings>` = **0** · `AssetDatabase.LoadAssetAtPath` 도 null · 강제 재임포트·Refresh 후에도 동일)
`ServerInfo.Awake`(`ServerInfo.cs:45`)가 `IndexOutOfRangeException` 으로 죽고 `OnClick_DevLogin` 이 진행되지 않는다.
파일·meta·스크립트 GUID 는 디스크에 정상 존재 → **Library 시딩(robocopy) 잔재**로 보이며 이번 변경과 무관하다.
Play 는 Title 에서 시작·정지했고 씬 dirty 0 으로 되돌렸다.
- 존 리듬의 **절대 HP 값**은 여전히 「제안값」이다. 플레이어 실 DPS 미측정(813m/813 S 트랙) — DPS 가 정해지면
`n_MonsterHP = 목표 TTK × DPS / f_BaseHPRate` 로 6행을 한 번에 다시 계산한다.
- 보스 등장 방식은 **맵 로드 즉시 상시 배치**다(`FieldBossData.Start()`). "존 전멸 → 보스 스폰" 게이트는 코드가 필요해 813d(G)로 넘겼다.
## 3. 롤백
1. `MonsterAppear.json` 에서 `n_SpawnerID``813001`~`813005`·`813010` 인 **6행 삭제**(기존 46행은 바이트 그대로라 앞부분은 손댈 필요 없다).
2. `WL_Nature.prefab`: `maplv/1~5``SpawnerID``1~5` 로 되돌리고, `FieldBoss` 컨테이너(`&8130050000000000001`~`&8130050000000000005` 문서 5개)와
루트 Transform `m_Children``{fileID: 8130050000000000002}` 줄을 지운다.
3. 또는 병합 커밋을 `git revert -m 1`. 다른 맵·다른 스포너 행에 영향 0.
## 4. 다음 바퀴 값 조정 지점
| # | 무엇 | 근거 |
|---|---|---|
| 1 | **리젠 방식** — 기준서 §B 요소1 은 «존 전멸 후 4~6 s 일괄 재등장(`PhaseAllKill`)» 인데 이번엔 발주서 §1 이 지정한 초안 값(`Random` 1.2~1.5 s 개별 리젠)을 그대로 넣었다. 존1~3 을 `PhaseAllKill` + `f_SpawnerDelay 4~6` 으로 바꾸면 "비었다 → 다시 찬다" 페이싱이 생긴다. **단** `PhaseAllKill` 은 인스턴스 = 종류×마릿수라 존3(6종×14=84)은 풀이 커진다 → 종류를 3~4 로 줄여야 한다 | 기준서 §B · `MobControlMgr.cs:118-128, 213-224` |
| 2 | **보스 추적 사거리** — Anubis `f_BaseChaseRange` **50**. 아레나 반경 20 을 넘어 존1(24 m)·존4(20 m)까지 끌려 나온다 → xlsm `MonsterList` 에서 15~20 으로 | 실측 · 초안 코드변경목록 3 |
| 3 | **드랍** — 존·보스 6행 전부 `n_DropReward 9700001` 공용 백, 보스 `MonsterList.n_DropItem 0`. 보스 3~5건 폭발 드랍은 새 백 필요 | 기준서 §B 요소4 · 813f |
| 4 | **존5 마릿수** — 5마리는 기준서 «밀집 8~15» 밖이다. 의도적(엘리트 = «8~12 s 짜리 벽»)이지만 기준서 채점 시 요소1 로 세지 말 것 | 기준서 §B 요소1 |
| 5 | **보스 HP 재계산** — 450 은 DPS 100 「제안」 기반. 실 DPS 측정 후 재산출 | 위 미확인 |
| 6 | **존4 PhaseAllKill 총 길이** — 3웨이브 × 8마리 × 3 s ≈ 72 s + 웨이브 간 2 s. 모바일 3분 런 기준으로 길면 마릿수를 6 으로 | `MobControlMgr.cs:213-224` |
## 5. 검증 도구
`AgentScripts/WL813e_Zones.cs` (Assets 밖 · 게임 빌드에 안 들어간다)
```
unity command run_script --file AgentScripts/WL813e_Zones.cs --entry WL813e_Zones.Edit # (a)~(f) 전수
unity command run_script --file AgentScripts/WL813e_Zones.cs --entry WL813e_Zones.Nav # 스포너·보스 도달성 스윕
unity command run_script --file AgentScripts/WL813e_Zones.cs --entry WL813e_Zones.Arena # 아레나 후보 재탐색
unity command run_script --file AgentScripts/WL813e_Zones.cs --entry WL813e_Zones.Watch # Play 60 s 실측(로그인 후)
unity command run_script --file AgentScripts/WL813e_Zones.cs --entry WL813e_Zones.Result # 결과
```
출력 원본 = `AgentScripts/staging/WL813e/{ZONES_EDIT,ZONES_NAV,ZONES_ARENA}.txt`