63 lines
4.6 KiB
Markdown
63 lines
4.6 KiB
Markdown
# 맵 10개 생성 (랜덤 배경 + 몬스터 2마리) 설계
|
|
|
|
- 날짜: 2026-06-06
|
|
- 브랜치: feature/maps-batch (신규)
|
|
- 대상: `map/map02.map`~`map11.map`(신규), `Global/SectorConfig.config`, `tools/gen-maps.mjs`(신규)
|
|
|
|
## 목표
|
|
|
|
`map01`을 템플릿으로 **독립 맵 10개(`map02`~`map11`)** 를 생성한다. 각 맵은 **서로 다른 공식 배경**을 갖고, **몬스터 2마리**가 랜덤 위치에 배치된다.
|
|
|
|
## 범위
|
|
|
|
### 포함
|
|
- `map02`~`map11` (신규 10개 맵 파일)
|
|
- 맵마다 다른 배경(`BackgroundComponent.TemplateRUID`) — 공식 MapleStory 배경 라이브러리에서 10개 서로 다르게
|
|
- 맵마다 몬스터 2마리, x 위치 랜덤(바닥 위), y는 바닥 높이 고정
|
|
- `SectorConfig.config`에 `map://map02`~`map://map11` 등록
|
|
- 재현용 생성기 `tools/gen-maps.mjs`
|
|
|
|
### 제외 (YAGNI)
|
|
- 맵 간 포털/이동 연결 (독립 맵)
|
|
- 맵별 다른 타일맵/지형 (map01 타일·바닥 그대로 복제)
|
|
- 카드-전투 로직 연동
|
|
- map01 변경
|
|
|
|
## 몬스터 전략 (스파이크 게이트)
|
|
|
|
사용자 선택: **라이브러리에서 다양한 몬스터**. 단, 리소스 검색이 RUID만 반환하고 action(stand/hit/die) 그룹핑·이름을 주지 않아 "완결된 몬스터" 조립이 불확실하다. 따라서:
|
|
|
|
- **A. 라이브러리 다양 몬스터 (1차 시도)**: 라이브러리에서 완결된 몬스터 2~3종(스프라이트 + stand/hit/die 애니메이션 RUID 세트)을 조립한다. **먼저 1개 맵으로 스파이크** → Maker Play에서 로드·렌더 검증.
|
|
- **게이트**: 스파이크에서 라이브러리 몬스터가 정상 렌더되면 → 10개 맵에 A로 확대. 조립/로드 실패 시 → **B로 폴백**.
|
|
- **B. 폴백 — 기존 몬스터 변형**: 이미 정상 로딩되는 기존 템플릿(StaticMonster/MoveMonster/ChaseMonster/monster-43)의 검증된 RUID 세트에서 맵당 랜덤 2종 + 랜덤 위치. 다양성은 ~4종으로 제한되지만 확실히 동작.
|
|
|
|
> 핵심 리스크: 이전에 **사용자 업로드(계정) 리소스는 로컬 워크스페이스 플레이에서 로드 실패**했다. 공식 라이브러리 리소스(배경/몬스터)는 shipped 콘텐츠라 로드될 것으로 보지만(기존 배경·몬스터 RUID가 정상 로딩 중), **확정 전 스파이크로 검증**한다.
|
|
|
|
## 구현 방식
|
|
|
|
### 생성기 `tools/gen-maps.mjs`
|
|
1. `map/map01.map`을 텍스트로 읽어 JSON 파싱(템플릿)
|
|
2. 배경 RUID 풀(10개, 공식 라이브러리에서 확보), 몬스터 정의 풀(A: 라이브러리 세트 / B: 기존 템플릿 세트)을 데이터로 보유
|
|
3. `NN = 02..11` 각각:
|
|
- 엔티티 deep-copy, **모든 엔티티 `id` GUID 재발급**(oldId→newId 매핑). `root_entity_id`/`sub_entity_id`가 엔티티 id를 가리키면 함께 치환. (component 안의 리소스 RUID — SpriteRUID, ActionSheet, TemplateRUID, CollisionGroup.Id, DamageSkinId, 타일셋 id — 는 엔티티 id가 아니므로 유지)
|
|
- `EntryKey`를 `map://mapNN`, 모든 `path`의 `/maps/map01`→`/maps/mapNN`, `name`을 `mapNN`로 치환
|
|
- `Background` 엔티티의 `TemplateRUID`를 `backgrounds[NN]`로 설정
|
|
- 기존 몬스터 엔티티들을 제거하고, 선택된 몬스터 2종을 랜덤 x 위치로 추가(각 몬스터는 템플릿 몬스터 엔티티를 복제하고 SpriteRUID/ActionSheet[A] 또는 그대로[B] + Position.x 랜덤)
|
|
- `map/mapNN.map`로 기록(원본 줄바꿈/포맷 보존 방식은 가능하면, 아니면 표준 JSON 직렬화)
|
|
4. `Global/SectorConfig.config`의 `Sectors[0].entries`에 `map://map02`~`map11` 추가(중복 방지)
|
|
|
|
랜덤은 결정론을 위해 인덱스 기반 시드(맵 번호로 위치/선택 산출) 사용 — 재실행 시 동일 결과.
|
|
|
|
### GUID 재발급 주의
|
|
- 엔티티 id 충돌 방지를 위해 맵마다 고유 GUID 필요. 자기참조(`root_entity_id`==자기 id)는 매핑으로 일관되게 치환.
|
|
|
|
## 검증
|
|
|
|
1. **스파이크(A)**: map02 1개만 생성 → reload→play→screenshot + Lua로 몬스터 엔티티/스프라이트 로드 확인. 실패 시 B로 전환.
|
|
2. 전체 생성 후: 각 맵(또는 표본)에서 reload→play(해당 맵)→screenshot으로 배경 상이·몬스터 2마리 확인. 맵 전환은 Maker에서 해당 맵을 열거나 sector 이동으로.
|
|
3. JSON 유효성(JSON.parse) + SectorConfig 10개 등록 확인 + 엔티티 id 중복 없음 확인.
|
|
|
|
## 산출물/형상관리
|
|
- 신규 파일 `map/map02.map`~`map11.map`, `tools/gen-maps.mjs`, `SectorConfig.config` 변경을 커밋.
|
|
- 배경/몬스터는 공식 라이브러리 RUID(문자열)만 참조 — 별도 리소스 파일 불필요(공식 콘텐츠). (단 A가 로컬 임포트를 요구하면 그 리소스 파일도 포함)
|