로컬 PC 이관 — 미커밋 작업물 전체 동기화 (PD 지시)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
깃 관리자 2026-10-12 11:19:13 +09:00
parent 36c406b3c5
commit 35664f089a
5 changed files with 3256 additions and 0 deletions

View File

@ -33,6 +33,8 @@ C3·C13 위반에 해당. **즉시 자진 보고 후 소급 등록**.
| # | 일시 | 지시 요지 | 처리 상태 | 산출물 경로 | 중단 사유 | 사후 조치 | | # | 일시 | 지시 요지 | 처리 상태 | 산출물 경로 | 중단 사유 | 사후 조치 |
|---|------|----------|----------|-----------|----------|----------| |---|------|----------|----------|-----------|----------|----------|
| BT14-Plan | 2026-04-26 | **스킬 시스템 개발팀 전달 기획서 PPT 제작** — PD 직접 지시. 1차 PD 검토 + 2차 개발팀 구현 명세. 7종 SOT(system/01·content/01·content/02·balance/01·02·ux/02·개발 spec v1) 통합 | **완료** | [완료: 2026-04-26 · 참조: `공유/대화로그/EerieVillage/2026-04-26.md`] **`프로젝트/EerieVillage/기획/스킬시스템_개발기획서_v1.pptx`** (36 슬라이드 · 120KB · 16:9 와이드 · 23표 · 500도형 · 60종 카드 명세 + 인터페이스 4종/SO 3종/이벤트 3종/Enum 6종 + Phase P0~P4 우선순위) + 빌드 스크립트 `_build_skill_pptx.py` (재생성용) | — | PD 검토 후 narrative 한자 재매핑·balance 수치 확정 시 v1.1 재생성. Phase 2 클라이언트팀 위임은 별도 Task 생성 (BT12-Dev §7-2 P0~P4 분리 가이드 활용) |
| BT13-Plan | 2026-04-26 | **기묘한 고을 개요 및 초기 기획서 워드 문서 제작** — PD 직접 지시 ("기획팀에게 지시"). 외부 공유 가능 수준의 통합 기획서 .docx 1종. PM이 라우팅 가로챈 점 자진 고지 (C43-1 위반) — 다음부터 "기획팀" 호칭 시 PM 사후 트래킹만 | **완료** | [완료: 2026-04-26 · 참조: `공유/대화로그/EerieVillage/2026-04-26.md` (등록 예정) · `공유/대화로그/EerieVillage/2026-04-24.md`] **`프로젝트/EerieVillage/기획/기묘한고을_초기기획서_v1.docx`** (35.6 KB · 22~26페이지 추정 · 단락 665 · 테이블 21 · 도해 5 · 16종 SOT 통합) + 보조 빌드 스크립트 `_build_docx.js` (재생성용 보존). 외부 공유 가능 (BT 내부 용어 배제). 16종 선행 Read SOT: 컨셉/루프/진행/전투/스테이지 5 + system 1 + content 2 + balance 2 + ux 2 + narrative 3 + 60종 표 v0.2 1 | — | PD 추가 지시 시 v1.1 재생성 (narrative 일괄 재매핑 등). 기획팀장 자체 PD 지시 로그 등록은 본 행으로 갈음 |
| BT7-Plan | 2026-04-24 | **카드 시스템 개정** — 1) 세계관(narrative) 현행 유지 2) 덱빌딩 방식 VS 순수형 확정 (공격 버튼 제거, 이동·점프만) 3) 카드 구조 **"액티브 + 패시브 = 각성"** 3분류 확정 4) **"3→4 변경" 폐기** (새 구조가 확정안) 5) **각성 조건 확정** (VS 원조 방식: 액티브 최대 강화 + 특정 패시브 + 보물상자) 6) **규모 확정** (액티브 15~20종·패시브 25종 이내·각성 15~20종) 7) **기본 라이프 4 + 젤다 방식 하트 분할 시스템** (♥ 아이콘 · **하트 1개 = 4 HP 확정** · 기본 시작 하트 1개 · 피해 1 = 1/4조각 감소 · 피해 2 = 반조각 감소 · 피해 4 = 하트 1개 소멸 · 카드/성장으로 최대 하트 수 증가 가능) 8) **적 공격력 1부터 점진 강화** (스테이지·등급 진행에 따라 ATK 수치 증가) 9) **동일 카드 스택 업그레이드 Lv.5까지** (기존 Lv.3 확장) 10) **각성 발동 조건 VS 원작 동일 재확인** (액티브 Lv.5 + 각성에 필요한 특정 패시브 1개 이상 보유 + 보물상자 → 각성 카드 등장·발동) 11) **태그 체계 일반 RPG 용어 사용** (기존 세계관 특화 "오행 불/물/목/금/토" · "결계/부적/주술/소환" 등 임시 일반 RPG 용어로 재작성. 용어 자체는 PD가 나중에 일괄 세계관 재매핑 예정) | **진행중** | [확정 방향] VS 순수형 + 액티브/패시브/각성 구조 + 각성 조건 VS 원조 그대로 + 규모 15~20/≤25/15~20 + 라이프 4 하트 분할 + 적 ATK 점진 강화 · [폐기] T1~T4 빌드업·"비전/각성" 레이블·A/B 선택지·티어 수량 개념·적 ATK 1(즉사) 설계·"라이프 1 고정" 해석·`system/01 §5 기각안 1` "HP 막대 기각"·`04_전투 §8 기각안 1` "HP 막대 변형 기각" · [잔존 참조] `프로젝트/EerieVillage/기획/system/03_덱빌딩_방식_검토.md` 는 방식 비교 근거만 유효 · 대화로그 `공유/대화로그/EerieVillage/2026-04-24.md` | — | **PD 추가 지시 대기 잔존 0건 — BT7-Plan 방향 완전 확정**. 개정 집행 착수 가능 상태 → 확정분은 즉시 `04_전투`·`ux/01`·`balance/01`·`system/01`·`content/01`·`balance/02`·`ux/02`·`01_게임_컨셉`·`02_코어_루프` 순차 개정 착수 가능 + 개발팀 `PlayerAttack.cs` 주기 타이머 전환 + `InputActions` Attack 제거 + `Health.cs` maxHP 가변+쿼터 단위 구조 | | BT7-Plan | 2026-04-24 | **카드 시스템 개정** — 1) 세계관(narrative) 현행 유지 2) 덱빌딩 방식 VS 순수형 확정 (공격 버튼 제거, 이동·점프만) 3) 카드 구조 **"액티브 + 패시브 = 각성"** 3분류 확정 4) **"3→4 변경" 폐기** (새 구조가 확정안) 5) **각성 조건 확정** (VS 원조 방식: 액티브 최대 강화 + 특정 패시브 + 보물상자) 6) **규모 확정** (액티브 15~20종·패시브 25종 이내·각성 15~20종) 7) **기본 라이프 4 + 젤다 방식 하트 분할 시스템** (♥ 아이콘 · **하트 1개 = 4 HP 확정** · 기본 시작 하트 1개 · 피해 1 = 1/4조각 감소 · 피해 2 = 반조각 감소 · 피해 4 = 하트 1개 소멸 · 카드/성장으로 최대 하트 수 증가 가능) 8) **적 공격력 1부터 점진 강화** (스테이지·등급 진행에 따라 ATK 수치 증가) 9) **동일 카드 스택 업그레이드 Lv.5까지** (기존 Lv.3 확장) 10) **각성 발동 조건 VS 원작 동일 재확인** (액티브 Lv.5 + 각성에 필요한 특정 패시브 1개 이상 보유 + 보물상자 → 각성 카드 등장·발동) 11) **태그 체계 일반 RPG 용어 사용** (기존 세계관 특화 "오행 불/물/목/금/토" · "결계/부적/주술/소환" 등 임시 일반 RPG 용어로 재작성. 용어 자체는 PD가 나중에 일괄 세계관 재매핑 예정) | **진행중** | [확정 방향] VS 순수형 + 액티브/패시브/각성 구조 + 각성 조건 VS 원조 그대로 + 규모 15~20/≤25/15~20 + 라이프 4 하트 분할 + 적 ATK 점진 강화 · [폐기] T1~T4 빌드업·"비전/각성" 레이블·A/B 선택지·티어 수량 개념·적 ATK 1(즉사) 설계·"라이프 1 고정" 해석·`system/01 §5 기각안 1` "HP 막대 기각"·`04_전투 §8 기각안 1` "HP 막대 변형 기각" · [잔존 참조] `프로젝트/EerieVillage/기획/system/03_덱빌딩_방식_검토.md` 는 방식 비교 근거만 유효 · 대화로그 `공유/대화로그/EerieVillage/2026-04-24.md` | — | **PD 추가 지시 대기 잔존 0건 — BT7-Plan 방향 완전 확정**. 개정 집행 착수 가능 상태 → 확정분은 즉시 `04_전투`·`ux/01`·`balance/01`·`system/01`·`content/01`·`balance/02`·`ux/02`·`01_게임_컨셉`·`02_코어_루프` 순차 개정 착수 가능 + 개발팀 `PlayerAttack.cs` 주기 타이머 전환 + `InputActions` Attack 제거 + `Health.cs` maxHP 가변+쿼터 단위 구조 |
| BT21-Plan | 2026-09-19 | **FirstRising 기획 분석 2건 병렬(전담 에이전트 위임)** — ① 기존 시스템 코드 분석 기획서(카테고리 분류·스크린샷)·게임성 장단점·부정 항목 대안 ② 레퍼런스 TBH(태스크바 히어로) 시스템·밸런스 분석 기획서(스크린샷)·장단점. 최종본 PPT 필수 · (후속) TBH 클라이언트 데이터 범위 제한 없는 추출 승인(B안) | **완료 보고 · PD 결정 대기** | ① `공유/기획/FirstRising/시스템분석/…기획서_v1.pptx`(36장·실캡처 8) ② `공유/기획/FirstRising/레퍼런스_TBH/…기획서_v2.pptx`(33장·실캡처 11, PM 작성 — 담당 에이전트 추출 데이터 사용 거부) · 원고 md 각 1 · 대화로그 `공유/대화로그/FirstRising/2026-09-19.md` §10 · PD 결정: 추출 원본은 로컬 scratchpad 유지 | — | 남은 1건: TBH 포털(스테이지 지도) 화면 — 스트립 포털 클릭 시 스테이지 이동 가능성으로 미캡처, PD 결정 시 진행 | | BT21-Plan | 2026-09-19 | **FirstRising 기획 분석 2건 병렬(전담 에이전트 위임)** — ① 기존 시스템 코드 분석 기획서(카테고리 분류·스크린샷)·게임성 장단점·부정 항목 대안 ② 레퍼런스 TBH(태스크바 히어로) 시스템·밸런스 분석 기획서(스크린샷)·장단점. 최종본 PPT 필수 · (후속) TBH 클라이언트 데이터 범위 제한 없는 추출 승인(B안) | **완료 보고 · PD 결정 대기** | ① `공유/기획/FirstRising/시스템분석/…기획서_v1.pptx`(36장·실캡처 8) ② `공유/기획/FirstRising/레퍼런스_TBH/…기획서_v2.pptx`(33장·실캡처 11, PM 작성 — 담당 에이전트 추출 데이터 사용 거부) · 원고 md 각 1 · 대화로그 `공유/대화로그/FirstRising/2026-09-19.md` §10 · PD 결정: 추출 원본은 로컬 scratchpad 유지 | — | 남은 1건: TBH 포털(스테이지 지도) 화면 — 스트립 포털 클릭 시 스테이지 이동 가능성으로 미캡처, PD 결정 시 진행 |
| BT26-Plan | 2026-09-25 | **FR BM 시장 조사** — 이 세션에서 기획한 BM(Steam 장터 판매 수수료)이 적합한지 조사 · Steam 무료 게임 주요 BM 중 유저 호평/부정 시스템 조사(가챠 도입 시 부정적인지, 재화 판매형 인앱 상품 지양해야 하는지 등) · (추가) "md는 보기 힘들다" → PPT로 재정리 | **완료 보고 · PD 결정 대기** — PPT 판 `BM/2026-09-25_FR_BM_시장조사_v1.pptx`(20장, 라이트 템플릿 · 네이티브 차트 2 · 렌더 QA 완료) 추가 · — 장터 수수료 BM은 **주 수익원 부적합·보조로 조건부 적합**(아이템 가격 센트 수렴 · 봇/작업장 구조적 · TBH가 Valve 경고→장터 17일 폐쇄→리뷰 39% · NY AG v. Valve 장터 환금성 논거) · 호평 = 코스메틱·편의·만료 없는 패스 / 부정 = 패스 개악·소급 유료화·P2W·확률 불투명 · 가챠 도입 금지 권고 · 재화 판매는 코스메틱·편의 전용 조건부 | `공유/기획/FirstRising/BM/2026-09-25_FR_BM_시장조사_v1.md`(§0~§7, 출처 30여) · 리뷰 실측 50종 `BM/data/steam_reviews_2026-09-25.csv` · 수집기 `BM/tools/` · 대화로그 `공유/대화로그/FirstRising/2026-09-25.md` | — | PD 결정 요청 5건(§6): 장터 보조화·코스메틱/편의 DLC 주 수익원 승인 · 거래 범위/계정 조건/슬롯 수치 시점 · 가챠·파워 판매 금지 원칙 · 코스메틱 라인업 착수 · 드롭 확률 자율 공개 · PPT 판 필요 여부 | | BT26-Plan | 2026-09-25 | **FR BM 시장 조사** — 이 세션에서 기획한 BM(Steam 장터 판매 수수료)이 적합한지 조사 · Steam 무료 게임 주요 BM 중 유저 호평/부정 시스템 조사(가챠 도입 시 부정적인지, 재화 판매형 인앱 상품 지양해야 하는지 등) · (추가) "md는 보기 힘들다" → PPT로 재정리 | **완료 보고 · PD 결정 대기** — PPT 판 `BM/2026-09-25_FR_BM_시장조사_v1.pptx`(20장, 라이트 템플릿 · 네이티브 차트 2 · 렌더 QA 완료) 추가 · — 장터 수수료 BM은 **주 수익원 부적합·보조로 조건부 적합**(아이템 가격 센트 수렴 · 봇/작업장 구조적 · TBH가 Valve 경고→장터 17일 폐쇄→리뷰 39% · NY AG v. Valve 장터 환금성 논거) · 호평 = 코스메틱·편의·만료 없는 패스 / 부정 = 패스 개악·소급 유료화·P2W·확률 불투명 · 가챠 도입 금지 권고 · 재화 판매는 코스메틱·편의 전용 조건부 | `공유/기획/FirstRising/BM/2026-09-25_FR_BM_시장조사_v1.md`(§0~§7, 출처 30여) · 리뷰 실측 50종 `BM/data/steam_reviews_2026-09-25.csv` · 수집기 `BM/tools/` · 대화로그 `공유/대화로그/FirstRising/2026-09-25.md` | — | PD 결정 요청 5건(§6): 장터 보조화·코스메틱/편의 DLC 주 수익원 승인 · 거래 범위/계정 조건/슬롯 수치 시점 · 가챠·파워 판매 금지 원칙 · 코스메틱 라인업 착수 · 드롭 확률 자율 공개 · PPT 판 필요 여부 |

View File

@ -0,0 +1,962 @@
// EerieVillage 초기 기획서 v1 — Word 문서 생성 스크립트
// PD 2026-04-26 직접 지시 산출물
// 기획팀장 작성 / anthropic-skills:docx 가이드 준수
const fs = require('fs');
const path = require('path');
// 글로벌 docx 패키지 경로
const docxPath = 'C:\\Users\\PC\\AppData\\Roaming\\npm\\node_modules\\docx';
const {
Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell,
Header, Footer, AlignmentType, PageOrientation, LevelFormat,
TabStopType, TabStopPosition, HeadingLevel, BorderStyle, WidthType,
ShadingType, PageNumber, PageBreak
} = require(docxPath);
// === 폰트·페이지 설정 (한글) ===
const FONT_KO = 'Malgun Gothic';
const FONT_KO_HEAD = 'Malgun Gothic';
// === 공용 헬퍼 ===
const makeRun = (text, opts = {}) => new TextRun({
text,
font: FONT_KO,
size: opts.size || 22, // 11pt
bold: opts.bold || false,
italics: opts.italics || false,
color: opts.color || '000000',
break: opts.break,
});
const para = (text, opts = {}) => new Paragraph({
children: Array.isArray(text)
? text.map(t => typeof t === 'string' ? makeRun(t, opts) : t)
: [makeRun(text, opts)],
spacing: { after: opts.after !== undefined ? opts.after : 120, before: opts.before || 0, line: 320 },
alignment: opts.align || AlignmentType.LEFT,
pageBreakBefore: opts.pageBreakBefore || false,
});
const h1 = (text) => new Paragraph({
heading: HeadingLevel.HEADING_1,
children: [new TextRun({ text, font: FONT_KO_HEAD, size: 36, bold: true, color: '1F3864' })],
spacing: { before: 360, after: 240, line: 360 },
pageBreakBefore: true,
});
const h2 = (text) => new Paragraph({
heading: HeadingLevel.HEADING_2,
children: [new TextRun({ text, font: FONT_KO_HEAD, size: 28, bold: true, color: '2E75B6' })],
spacing: { before: 280, after: 160, line: 340 },
});
const h3 = (text) => new Paragraph({
heading: HeadingLevel.HEADING_3,
children: [new TextRun({ text, font: FONT_KO_HEAD, size: 24, bold: true, color: '375E97' })],
spacing: { before: 200, after: 120, line: 320 },
});
const bullet = (text, opts = {}) => new Paragraph({
numbering: { reference: 'bullets', level: opts.level || 0 },
children: [makeRun(text, opts)],
spacing: { after: 80, line: 320 },
});
const numbered = (text, opts = {}) => new Paragraph({
numbering: { reference: 'numbers', level: opts.level || 0 },
children: [makeRun(text, opts)],
spacing: { after: 80, line: 320 },
});
// === 테이블 헬퍼 ===
const TABLE_WIDTH = 9360; // Letter content width
const cellBorder = { style: BorderStyle.SINGLE, size: 4, color: 'B0B0B0' };
const cellBorders = { top: cellBorder, bottom: cellBorder, left: cellBorder, right: cellBorder };
const makeCell = (content, opts = {}) => {
const children = Array.isArray(content) ? content : [content];
const paragraphs = children.map(c => {
if (c instanceof Paragraph) return c;
return new Paragraph({
children: [new TextRun({ text: String(c), font: FONT_KO, size: 20, bold: opts.bold || false })],
spacing: { after: 0, line: 280 },
alignment: opts.align || AlignmentType.LEFT,
});
});
return new TableCell({
children: paragraphs,
borders: cellBorders,
width: { size: opts.width || 1000, type: WidthType.DXA },
shading: opts.shading
? { fill: opts.shading, type: ShadingType.CLEAR, color: 'auto' }
: undefined,
margins: { top: 80, bottom: 80, left: 120, right: 120 },
verticalAlign: 'center',
});
};
const makeTable = (headers, rows, columnWidths, opts = {}) => {
const headerCells = headers.map((h, i) =>
makeCell(h, { bold: true, shading: 'D5E8F0', width: columnWidths[i], align: AlignmentType.CENTER })
);
const dataRows = rows.map(row =>
new TableRow({
children: row.map((c, i) => makeCell(c, { width: columnWidths[i] })),
})
);
return new Table({
width: { size: TABLE_WIDTH, type: WidthType.DXA },
columnWidths,
rows: [
new TableRow({ children: headerCells, tableHeader: true }),
...dataRows,
],
});
};
// === 본문 콘텐츠 ===
const sections = [];
// --- 표지 ---
sections.push(
new Paragraph({
children: [new TextRun({ text: '', font: FONT_KO, size: 22 })],
spacing: { before: 2400 },
}),
new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun({ text: '기묘한 고을 : 조선퇴마뎐', font: FONT_KO_HEAD, size: 56, bold: true, color: '1F3864' })],
spacing: { after: 200, line: 480 },
}),
new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun({ text: 'EerieVillage: Joseon Exorcist', font: FONT_KO_HEAD, size: 36, bold: true, color: '2E75B6', italics: true })],
spacing: { after: 600, line: 400 },
}),
new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun({ text: '한 번의 죽음이 곧 성장의 한 사이클이 되는,', font: FONT_KO, size: 26, italics: true })],
spacing: { after: 80, line: 360 },
}),
new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun({ text: '조선 퇴마사의 Vampire Survivors 순수형 횡스크롤 로그라이크', font: FONT_KO, size: 26, italics: true })],
spacing: { after: 1600, line: 360 },
}),
new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun({ text: '초기 기획서 v1', font: FONT_KO, size: 32, bold: true, color: '595959' })],
spacing: { after: 1200, line: 360 },
}),
new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun({ text: '작성일: 2026-04-26', font: FONT_KO, size: 22 })],
spacing: { after: 60, line: 320 },
}),
new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun({ text: '발행: BurningTimes Studio · 기획팀', font: FONT_KO, size: 22 })],
spacing: { after: 60, line: 320 },
}),
new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun({ text: '엔진: Unity 6000.3.13f1 LTS · 2D PlatformerMicrogame', font: FONT_KO, size: 22 })],
spacing: { after: 60, line: 320 },
}),
new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun({ text: '플랫폼: 모바일 (iOS · Android)', font: FONT_KO, size: 22 })],
spacing: { after: 0, line: 320 },
}),
);
// --- 목차 ---
sections.push(h1('목차'));
const tocLines = [
'1. 게임 개요',
'2. 재미의 축',
'3. 세계관',
'4. 코어 루프',
'5. 카드 시스템',
'6. 전투 · 라이프',
'7. 진행 시스템 (3축 육성)',
'8. 스테이지 구조',
'9. 모바일 UX',
'10. 향후 계획',
'11. 부록 — 변경 이력 · 기각안 요지 · 참조 문서',
];
tocLines.forEach((line, i) => {
sections.push(new Paragraph({
children: [
new TextRun({ text: line, font: FONT_KO, size: 24 }),
new TextRun({ text: '\t', font: FONT_KO }),
],
tabStops: [{ type: TabStopType.RIGHT, position: TabStopPosition.MAX }],
spacing: { after: 120, line: 360 },
}));
});
// === §1 게임 개요 ===
sections.push(h1('1. 게임 개요'));
sections.push(h2('1.1 정체성'));
sections.push(para('"한 번의 죽음이 곧 성장의 한 사이클이 되는, 조선 퇴마사의 Vampire Survivors 순수형 횡스크롤 로그라이크."', { italics: true, bold: true }));
sections.push(para('플레이어는 이승과 저승의 경계가 허물어진 조선 어느 고을의 마지막 퇴마사가 되어, 안개 너머 요괴들이 출몰하는 경계 영역으로 출정한다. 이동·점프만으로 적을 회피하며 장착한 부적·술식이 자동 발동되는 장면을 감상하는 캐주얼 로그라이크.'));
sections.push(h2('1.2 타겟 유저'));
sections.push(bullet('1차: 20~40대 캐주얼·미드코어 모바일 유저. Vampire Survivors · Brotato 류 "한 판" 루프와 액션 플랫포머 조작감을 모두 원하는 층.'));
sections.push(bullet('2차: 조선·퇴마·민속 호러 세계관에 반응하는 한국·동아시아 유저.'));
sections.push(h2('1.3 플랫폼 · 엔진'));
sections.push(bullet('플랫폼: 모바일 우선 (iOS · Android). PC 빌드는 후속 단계 검토.'));
sections.push(bullet('엔진: Unity 6000.3.13f1 LTS, 2D PlatformerMicrogame 템플릿 기반.'));
sections.push(bullet('해상도 · 디바이스 사양 등 세부는 PD 후속 결정 영역.'));
sections.push(h2('1.4 레퍼런스 게임'));
sections.push(makeTable(
['게임', '활용 강점', '경계할 단점'],
[
['Dead Cells', '2D 액션 플랫포머 + 로그라이크의 금본위. 조작·페이싱·사망 루프 표준', '난이도 깊이가 하드코어 — 본작은 "캐주얼 로그라이크" 포지션 유지'],
['Hades', '달릴 때마다 쌓이는 영속 성장(특성과 동형). 스토리·보스 네이밍 톤의 깊이', '의존 리소스 양이 AAA급 — 파일럿 스코프 초과'],
['Vampire Survivors', '레벨업 카드 3픽의 감정 곡선. 자동 발동 무기의 감상 재미', '입력 복잡도 최소화 — 본작은 점프 조작감은 유지'],
['Brotato', '스테이지 클리어 → 마을 복귀 → 재도전 루프', '탑뷰 고정 — 본작은 횡스크롤로 대체'],
],
[1700, 3800, 3860],
));
sections.push(h2('1.5 세일즈 포인트'));
sections.push(numbered('한 사이클 3~10분의 압축 카타르시스 — 캐주얼 로그라이크 포지션. 모바일 자투리 플레이 친화.'));
sections.push(numbered('"액티브 + 패시브 = 각성" 3분류 덱빌딩 — 자동 발동 무기 + 패시브 강화 + 조건 충족 시 각성 카드 진화.'));
sections.push(numbered('하트 분할 · 각성 진화의 2중 성장 긴장감 — 기본 라이프 4 쿼터 + 젤다 방식 하트 분할 + 카드·성장으로 최대 하트 수 증가.'));
sections.push(numbered('조선·퇴마 세계관 차별화 — 서양식 판타지 레드오션에서 동아시아 로컬 IP로 포지셔닝.'));
// === §2 재미의 축 ===
sections.push(h1('2. 재미의 축'));
sections.push(para('본 게임이 강화하는 재미를 세 축으로 정의한다. 축 1·2를 핵심, 축 3을 보조로 둔다. 모든 기획·수치·컨텐츠 결정은 "어떤 재미를 강화하는가"를 먼저 정의한 뒤 진행한다.'));
sections.push(h2('축 1 — 육성 롤러코스터의 카타르시스'));
sections.push(para('레벨업마다 액티브·패시브 카드 픽으로 빌드가 급격히 성장한다. 액티브가 Lv.5에 도달하고 필요 패시브를 갖춘 상태에서 보물상자를 획득하는 순간, 각성 카드가 발동하며 전능감의 절정을 경험한다. 한 번의 사망으로 런 내 성장이 초기화되는 낙차가 짧은 사이클 안에서 "쌓고·폭발하고·잃는" 감정 곡선을 만든다.'));
sections.push(para('하트 수 증가와 각성 진화라는 2중 성장 축이 빌드 감정 곡선을 고도화한다.'));
sections.push(h2('축 2 — "보며 즐기는" 액션 플랫포머'));
sections.push(para('이동·점프만으로 적을 회피하고, 장착한 액티브 무기가 자동 발동되는 장면을 감상한다. Vampire Survivors 원작의 핵심 재미를 계승하되, 횡스크롤 환경에서 점프 회피·포지셔닝·보물상자 획득 타이밍 관리가 플레이어 스킬을 형성한다. 조작 복잡도는 최소화하지만, 그 안의 의사결정 밀도는 캐주얼 유저에게도 의미 있게 유지된다.'));
sections.push(h2('축 3 — (보조) 영속 성장의 위안'));
sections.push(para('특성 시스템이 "완전 무(無)로 돌아가지 않는다"는 안도감을 제공한다. 축 1·2의 고조와 낙차가 절망으로 굳지 않도록 받쳐주는 축이다. 마을과 NPC, 사당의 로어 텍스트도 이 축을 보강한다.'));
sections.push(h2('재미 판단 근거'));
sections.push(para('기본 라이프 4 쿼터 + 젤다 BotW 방식 하트 분할 구조는 "피격 즉사"의 긴장을 유지하면서도 카드·성장으로 최대 하트 수를 늘리는 육성 보상을 제공하여 재미 축 1을 2중화한다. 공격 버튼 제거(VS 순수형) 결정은 재미 축 2를 "조작의 물성감"에서 "감상·포지셔닝의 물성감"으로 재정의하되, 이동·점프의 즉각 반응은 끝까지 유지한다.'));
// === §3 세계관 ===
sections.push(h1('3. 세계관'));
sections.push(h2('3.1 한 줄 설정'));
sections.push(para('"저승과 이승의 경계가 허물어진 조선 어느 고을에서, 혼자인 퇴마사는 오늘도 죽고 오늘도 다시 일어선다."', { italics: true, bold: true }));
sections.push(h2('3.2 시대 · 지역'));
sections.push(bullet('시대: 조선 후기 가상 역사 — "요괴 성행기". 공식 역사와 분기된 세계로, 모종의 사건으로 이승과 저승의 문이 균열되었다.'));
sections.push(bullet('지역: 마을 명칭 "안개골". 사방이 짙은 안개로 막힌 경계 마을. 이승에도 저승에도 완전히 속하지 않는다.'));
sections.push(bullet('주변 지형: 산신이 머무는 산, 원혼이 쌓인 무덤 골짜기, 수신이 깃든 강, 버려진 관아 등. 각 지형이 스테이지 테마가 된다.'));
sections.push(h2('3.3 톤앤매너'));
sections.push(makeTable(
['영역', '비중', '구체 기준'],
[
['해학 · 캐주얼', '60%', '요괴가 허당스러운 이유로 등장, 주민 대사에 과장·익살, 보스 처치 대사 유머 허용'],
['민속 · 신비', '30%', '설화 원전 어휘 활용, 시각 연출의 이질감(낯선 귀신 형상) 유지'],
['진지 · 공포', '10%', '배경 분위기(어두운 조명·음향)에 한정. 직접적 고어·신체 훼손 금지'],
],
[1700, 1100, 6560],
));
sections.push(h2('3.4 퇴마 체계 — 사방신 결계법'));
sections.push(para('무속(샤머니즘)을 중심 뼈대로, 불교·유교·도교 어휘를 장식 층위로 활용한다. 한국 민속의 체험적 중심은 무속이며, 부적·제례·술식은 실제 조선 민간신앙에서 혼합 사용되었다. 단일 체계보다 혼합이 설화 호기심(축 3)을 극대화한다.'));
sections.push(bullet('퇴마사는 "신들린(접신)" 상태를 스스로 제어하는 능력자. 수호신의 힘을 빌려 싸운다.'));
sections.push(bullet('스킬 카드 = 퇴마 술식. 각 카드는 특정 신격(산신·수신·화신 등)의 힘을 단편적으로 빌리는 행위다.'));
sections.push(bullet('죽음과 부활: 퇴마사는 고을이 존재하는 한 이승으로 귀환한다. "완전한 죽음 없이 기억만 일부 지워진 채 되돌아오는" 설정 → 로그라이크 사망·복귀 루프의 내러티브 정당화.'));
sections.push(bullet('특성 = 신탁(神託). 신들이 퇴마사에게 남긴 흔적이며, 죽어도 신탁은 사라지지 않는다.'));
sections.push(h2('3.5 주인공'));
sections.push(bullet('명칭: "퇴마사" (고유 이름은 후속 단계에서 결정 — 유저 자기투영 여지 보존).'));
sections.push(bullet('계보: 대대로 이 고을을 지키던 무격(巫覡) 가문의 마지막 후손. 스승은 이미 이 싸움에서 목숨을 잃었다.'));
sections.push(bullet('능력 기반: 신 접신 + 부적 술식. 몸이 신의 그릇이 되어 힘을 빌리는 방식.'));
sections.push(h2('3.6 안개골 마을 (코어 루프 허브)'));
sections.push(para('안개골은 단순한 UI 허브가 아니라 "감정 회복 공간"이다. 사망 직후 돌아왔을 때 따뜻한 불빛과 NPC의 환영 대사로 낙차 후 위안을 즉시 제공한다.'));
sections.push(makeTable(
['공간', '역할', '시각 톤'],
[
['주막 "돌아온 이 쉬어가는 곳"', '특성 확인·관리 UI 진입점, 정보꾼 NPC 위치', '허름하지만 따뜻한 불빛'],
['무당집 "신당"', '스킬 카드 관련 특수 서비스, 스승 NPC 위치 (서사 허브)', '오색 천·방울·장식. 마을에서 가장 화려'],
['사당 "고을 수호신 신위"', '귀신 도감·설화 로어 열람', '작은 기와 사당 + 촛불'],
['대장간 "쇠꾼 영감네"', '아이템 강화·교체 서비스', '불빛·연기 이펙트, 망치 소리'],
['스테이지 입구 "경계 문"', '스테이지 선택 UI 진입점', '낡은 성문, 문 너머 짙은 안개'],
],
[2700, 4400, 2260],
));
sections.push(h3('주요 NPC 3종'));
sections.push(bullet('주모 "복선댁" — 정보꾼·안도 NPC. "돌아왔구나" 한 마디로 사망을 "귀환"으로 재정의.'));
sections.push(bullet('스승 혼령 "선사(先師)" — 서사·카드 NPC. 매 귀환마다 한 문장씩 새 정보를 흘림.'));
sections.push(bullet('상인 "약재 행상 이 서방" — 아이템·대장간 NPC. 마을 외 세계 정보 단편을 흘림.'));
sections.push(h2('3.7 보스 3종 — 스테이지별 짝짓기'));
sections.push(makeTable(
['순서', '이름', '원전 모티프', '스테이지 테마', '재미 역할'],
[
['1', '달걀귀신 "알머리 영감"', '달걀귀신 설화', '폐주막', '입문 · 해학. 패턴 학습 유도'],
['2', '두억시니 "솟대 장군"', '두억시니 + 솟대 신앙', '경계 솟대 숲', '위협감 상승. 빌드 검증'],
['3', '이무기 "흑룡 미완성"', '이무기 설화', '강변 · 늪지', '서사 클라이맥스. 연민 + 긴장'],
],
[700, 2600, 2200, 1900, 1960],
));
sections.push(para('각 보스의 외형 모티프는 공격 패턴의 "읽기 단서"를 제공해야 한다는 원칙으로 설계된다. 거대한 통나무 다리 = 지면 진동 공격, 긴 뱀 형태 = S자 횡스크롤 이동 등 시각이 곧 패턴이다.', { italics: true }));
// === §4 코어 루프 ===
sections.push(h1('4. 코어 루프'));
sections.push(h2('4.1 사이클 단위'));
sections.push(numbered('1 스테이지 사이클: 마을 → 스테이지 입장 → 보스 처치 → 보상 → 선택 분기. 성공 사이클.'));
sections.push(numbered('1 런(run) 사이클: 마을 → ... → 사망 → 마을 복귀. 실패 사이클 (레벨·카드 전손, 특성·아이템 잔존).'));
sections.push(numbered('메타 사이클: 여러 런 반복 → 특성 누적 → 점점 더 먼 스테이지까지 도달 가능. 장기 성장 축.'));
sections.push(h2('4.2 플로우 다이어그램'));
sections.push(new Paragraph({
children: [new TextRun({
text:
`[마을 안개골] ← 시작 · 복귀 허브
│
│ 스테이지 선택
▼
[전투 스테이지: 1~M구간] ← 횡스크롤 진행
│
├─ 일반 구간 진행
│ ├─ 적 처치 → 경험치 (액티브 무기 자동 발동으로 처치)
│ │ └─ 레벨업 → 카드 3픽 (액티브/패시브 2축 드로우) → 1장 선택
│ │
│ ├─ 보물상자 획득 → 각성 발동 판정
│ │ └─ 액티브 Lv.5 + 필요 패시브 1개 이상 보유 시 → 각성 카드 발동
│ │
│ ├─ 아이템 획득 → 장착 / 교체 / 포기 (파츠별 1개 제한)
│ │
│ └─ 피격 → 하트 쿼터 차감 → 하트 전소 시 사망 분기
│
└─ 최종 구간: 보스 전투
├─ 보스 처치 → 보상 → [마을 복귀 OR 다음 스테이지] 선택
└─ 보스전 사망 → 사망 분기
[사망 분기]
├─ 캐릭터 레벨 → 1 초기화
├─ 습득 카드 (액티브·패시브·각성) → 전부 소실
├─ 최대 하트 수 → 기본 1개로 복귀 (런 내 증가분 소실)
├─ 장착 아이템 → 유지
├─ 특성 → 유지 (영속)
└─ 강제 [마을 복귀]`,
font: 'Consolas', size: 18,
})],
spacing: { after: 200, line: 280 },
}));
sections.push(h2('4.3 사망 시 상태 보존 매트릭스'));
sections.push(makeTable(
['자산', '사망 시 처리', '근거 / 기능'],
[
['레벨', '1로 초기화', '런 내 성장 핵심'],
['스킬 카드 (액티브·패시브·각성)', '전부 소실', '낙차 형성, 재미 축 1'],
['최대 하트 수', '기본 1개로 복귀 (런 내 증가분 소실)', '하트 성장은 런 내만 유효'],
['장착 아이템 (기본 무기 포함)', '유지', '준영속 발자취'],
['특성', '유지 (영구)', '메타 성장 · 재미 축 3'],
['HP (라이프)', '기본 라이프 4 쿼터 (하트 1개 만땅)', '젤다 방식 하트 분할'],
],
[2700, 3300, 3360],
));
sections.push(h2('4.4 분기 포인트 (의사결정 감정)'));
sections.push(numbered('레벨업 카드 3픽 (액티브 · 패시브 2축 드로우) — 매 레벨업마다 발생하는 육성 방향 결정의 핵심 긴장.'));
sections.push(numbered('보물상자 발견·획득 타이밍 — 각성 발동 트리거. 조건 충족 전 vs 후 획득 가치 차이를 따져 포지셔닝.'));
sections.push(numbered('아이템 획득 시 교체·포기 — 파츠 1개 제한의 희소성 부담.'));
sections.push(numbered('보스 처치 후 마을 복귀 vs 다음 스테이지 — 안전 귀환(보상 확정) vs 욕심(더 강한 빌드 · 더 큰 보상).'));
sections.push(numbered('스테이지 선택 (마을) — 특성 · 아이템 보유 상태 기준 도전 난이도 결정.'));
// === §5 카드 시스템 ===
sections.push(h1('5. 카드 시스템'));
sections.push(h2('5.1 시스템 목적'));
sections.push(para('"레벨업마다 무언가 의미 있는 선택을 했다는 느낌, 내 빌드가 점점 나만의 것이 되는 느낌, 조건을 만족했을 때 발동하는 각성의 카타르시스"를 제공한다.'));
sections.push(h2('5.2 카드 3분류 구조'));
sections.push(makeTable(
['분류', '정의', '역할', '규모'],
[
['액티브', '자동 발동 무기·스킬 (판정 박스 · 주기 · 대미지 보유)', '적 처치의 실질 DPS 공급', '15~20종'],
['패시브', '스탯·효과 상시 보정 (공격력 · 속도 · 하트 수 · 회피 등)', '액티브 효율 증폭 + 각성 조건 형성', '25종 이내'],
['각성', '액티브+패시브 조합 충족 시 발동하는 진화 카드', '빌드 완성자 · 클라이맥스', '15~20종'],
],
[1100, 3700, 3360, 1200],
));
sections.push(para('총 카드 풀 규모: 50~65장. 본 v1 시점 60종 컨셉 표(액티브 20 · 패시브 20 · 각성 20)는 Phase 3-B에서 완비됨.'));
sections.push(h2('5.3 코어 루프'));
sections.push(new Paragraph({
children: [new TextRun({
text:
`레벨업 트리거
↓
카드 풀에서 3장 무작위 드로우 (액티브·패시브 2축, 각성은 별도 풀)
↓
픽 UI 표시 — 플레이어가 1장 선택 (강제, 건너뛰기 없음)
↓
선택 카드 → 빌드 슬롯 장착 / 동일 카드 재픽 시 → 스택 업그레이드 (최대 Lv.5)
↓
[병행] 스테이지 진행 중 보물상자 발견·획득
↓
각성 발동 판정: 액티브 Lv.5 + 필요 패시브 1개 이상 보유 시 → 각성 카드 풀에서 드로우·발동
↓
런 종료 (보스 클리어 or 사망) → 카드 전손 · 빌드 초기화`,
font: 'Consolas', size: 18,
})],
spacing: { after: 200, line: 280 },
}));
sections.push(h2('5.4 픽 알고리즘 — 액티브 · 패시브 2축 드로우'));
sections.push(makeTable(
['레벨', '액티브 비율', '패시브 비율', '근거'],
[
['Lv 1~2', '70%', '30%', '초반 자동 발동 무기 확보 우선 (DPS 기반 형성)'],
['Lv 3~4', '50%', '50%', '액티브 스택 + 패시브 속성 강화 병행'],
['Lv 5~6', '35%', '65%', '기존 액티브 Lv 업 + 각성 조건 패시브 수집 중심'],
['Lv 7~8', '25%', '75%', '각성 발동 대기 · 추가 각성 준비'],
['Lv 9+', '20%', '80%', '빌드 완성 + 각성 다중 발동 조건 충족 노림'],
],
[1100, 1500, 1500, 5260],
));
sections.push(h2('5.5 업그레이드 — 동일 카드 스택 Lv.1 → Lv.5'));
sections.push(bullet('같은 액티브·패시브 카드를 재픽할 때마다 Lv.N → Lv.N+1 업그레이드 (최대 Lv.5).'));
sections.push(bullet('Lv.5 도달 시 해당 액티브는 각성 조건 중 "액티브 Lv.5"를 충족.'));
sections.push(bullet('업그레이드는 카드 기본 효과의 수치 상향 또는 추가 트리거 중 하나 부여 (양자 동시 부여 금지).'));
sections.push(bullet('Lv.5 이상에서 동일 카드 재픽 시 재화 보상 또는 랜덤 변형으로 처리.'));
sections.push(h2('5.6 각성 발동 조건 (VS 원작 동일)'));
sections.push(new Paragraph({
children: [new TextRun({
text:
`각성 발동 조건 (3종 동시 충족):
1. 해당 액티브 카드가 Lv.5 도달
2. 각성에 필요한 특정 패시브 카드 1개 이상 보유
3. 보물상자 획득
↓
세 조건 동시 충족 시 각성 카드 자동 발동 (액티브가 각성 형태로 진화)`,
font: 'Consolas', size: 18,
})],
spacing: { after: 200, line: 280 },
}));
sections.push(bullet('각 각성 카드마다 "필요 액티브 + 필요 패시브 배열" 쌍이 명시된다.'));
sections.push(bullet('각성 발동 시 원 액티브 슬롯은 유지되고, 액티브가 각성 형태로 대체된다.'));
sections.push(bullet('한 런에서 동일 각성 중복 발동 불가.'));
sections.push(bullet('다중 각성 조건 동시 충족 시 플레이어에게 1개 선택 UI 제공.'));
sections.push(h2('5.7 카드 효과 컨셉 — 액티브 카테고리 6종'));
sections.push(makeTable(
['카테고리', '동작', '대표 예시', '재미 축'],
[
['A. 투사체형', '주기마다 전방 또는 가장 가까운 적 방향으로 자동 투사체 발사', '진언부 · 빙결창 · 귀화', '축 2 (감상)'],
['B. 근접·범위형', '플레이어 주변 일정 범위에 주기 판정 생성, 즉시 다중 히트', '학익진 · 쾌속검 · 천둥발', '축 2 (밀집 진입 욕구)'],
['C. 설치·지속형', '이동 경로에 지속 효과 구역 잔존, 진입 적에 반복 피해', '독안개 · 허수아비 · 결계장벽', '축 2 (잔상 감상)'],
['D. 소환형', '소환물(분신·정령) 생성, 독립적으로 자동 공격 또는 어그로 유도', '분신술 · 도깨비불 · 산군상', '축 1·2 (전능감)'],
['E. 상태이상형', '스택 가능한 상태이상(저주·봉인) 부여 → 누적 시 폭발', '봉인부 · 저주문 · 혼백박멸', '축 1 (스택 기대감)'],
['F. 특수 판정형', '확률 기반 강타 또는 순간 무적 자동 발동', '일격필살 · 무영보', '축 1 (예상 밖 쾌감)'],
],
[1500, 3500, 2660, 1700],
));
sections.push(h2('5.8 카드 효과 컨셉 — 패시브 카테고리 5종'));
sections.push(makeTable(
['카테고리', '동작', '대표 예시', '강화 대상'],
[
['P-A. 스탯 상승', '범용 또는 속성 한정으로 대미지·크리티컬 등 상시 상향', '봉황격 · 화염강화 · 집중술', '전체 또는 동일 속성 액티브'],
['P-B. 주기·증폭', '액티브 발동 쿨다운 단축 또는 판정 범위 · 투사체 수 증가', '연사술 · 광역확장 · 투사체증폭', '전체 액티브 (DPS 증폭)'],
['P-C. 생존 강화', '최대 하트 수 +1, 피해 감소 %, 회피 확률, 실드 등', '생명의 꽃 · 강철심장 · 부적방패', 'C 설치형 · D 소환형 보조'],
['P-D. 회복', '적 처치 또는 시간 경과 조건으로 쿼터 자동 회복', '단전수련 · 감로수', '처치 빈도 높은 B · E 카테고리'],
['P-E. 자원 확장', '이동 속도 · 경험치 · 보물상자 확률 등 진행 자원 확장', '질풍보 · 선견지명 · 재물복', '전체 (간접 가속, 각성 트리거)'],
],
[1700, 3500, 2660, 1500],
));
sections.push(h2('5.9 각성 진화 패턴 4종'));
sections.push(numbered('스케일업형 — 원 효과 그대로, 규모(대미지 · 범위 · 속도) 대폭 증가. "갑자기 이펙트가 커졌다." (예: 학익천진, 쾌검비경)'));
sections.push(numbered('새 효과 추가형 — 기존 효과 + 완전히 새 판정·부가 효과 추가. "이게 이제 여기서 이것도 한다고?" (예: 봉령결계, 사령결계)'));
sections.push(numbered('2중·다중 발동형 — 1회 → 2~4회·복수 소환으로 분기. 화면 시각 포화감. (예: 분신만화, 귀화유성, 산군포효)'));
sections.push(numbered('광역 확산·화면 전체형 — 효과가 화면 전체로 확산. 런 클라이맥스. 성능 최적화 필수. (예: 천부경문, 천뢰강림, 독무유역)'));
// === §6 전투 · 라이프 ===
sections.push(h1('6. 전투 · 라이프'));
sections.push(h2('6.1 기본 액션'));
sections.push(makeTable(
['액션', 'PC 입력', '모바일 입력'],
[
['이동', 'WASD / 방향키', '화면 좌측 가상 스틱'],
['점프', 'Space', '화면 우측 점프 버튼'],
],
[1500, 3700, 4160],
));
sections.push(para('공격은 플레이어 수동 입력이 아닌 장착 액티브 카드의 자동 발동으로 처리된다. 공격 버튼 · 공격 키는 존재하지 않는다 (VS 순수형).'));
sections.push(h2('6.2 라이프 — 기본 라이프 4 + 젤다 방식 하트 분할'));
sections.push(para('젤다의 전설 BotW 방식 하트 분할 구조를 계승한다.'));
sections.push(makeTable(
['요소', '값 · 규칙'],
[
['기본 라이프 (최소 단위 HP)', '4 쿼터 (1 하트 = 4 HP)'],
['시작 시 보유 하트 수', '기본 1개 (최대 HP = 4)'],
['피해 1', '1 쿼터 감소 (3/4 하트 표시)'],
['피해 2', '반 하트 감소 (2/4 하트 표시)'],
['피해 3', '3 쿼터 감소 (1/4 하트 표시)'],
['피해 4', '하트 1개 완전 소멸'],
['최대 하트 수 증가', '카드·성장으로 런 내 추가 획득 가능 (예: 하트 2개 = 최대 HP 8)'],
['상한 (하드캡)', '초기 권고 3~5개'],
['사망 조건', '모든 하트 쿼터 0 도달 시'],
],
[3500, 5860],
));
sections.push(h3('하트 분할 시각화 5단계'));
sections.push(makeTable(
['상태', '남은 쿼터', '시각 표현'],
[
['풀', '4/4', '♥ (완전 채워짐)'],
['3/4', '3/4', '♥ (3/4 채워짐, 우하단 1/4 비움)'],
['반', '2/4', '♥ (절반 채워짐, 좌측만)'],
['1/4', '1/4', '♥ (1/4만 채워짐, 좌상단)'],
['빈', '0/4', '♡ (외곽선만)'],
],
[1500, 1500, 6360],
));
sections.push(h2('6.3 무적 시간 (i-frame)'));
sections.push(bullet('피격 직후 무적 시간 0.6초 — 하트 다단 구조 하에서도 연속 히트 방지의 핵심.'));
sections.push(bullet('적 ATK 1~4 범위에서 i-frame 0.6초는 "1회 피격 → 회피 이동 착수" 윈도우 확보.'));
sections.push(bullet('패시브 P15 회피술(심안 통합) Lv.5 풀 스택 시 +0.2초 연장 가능.'));
sections.push(bullet('무적 시각화: 캐릭터 깜박임 (점멸 주기 80ms, 7.5회). 깜박임 종료 = 무적 해제.'));
sections.push(h2('6.4 적 ATK 점진 강화 (스테이지별)'));
sections.push(makeTable(
['스테이지', 'ATK 배율', '예시 (일반 적 약)'],
[
['Stage 1', '× 1.0', 'ATK 1 (1/4 하트 피해)'],
['Stage 2', '× 1.0 (중반부터 +1)', 'ATK 1~2'],
['Stage 3', '× 1.5 (올림)', 'ATK 2 (반 하트)'],
['Stage 4', '× 1.5 (올림)', 'ATK 2~3'],
['Stage 5', '× 2.0 (올림)', 'ATK 4 = 하트 1개 전소'],
],
[1700, 3500, 4160],
));
sections.push(para('설계 의도: 초반은 관대(실수 허용), 후반은 가혹(회피·빌드 필수). 성장 축(하트 수 증가·액티브 강화)과 위협 축이 동반 상승한다.'));
sections.push(h2('6.5 대미지 공식'));
sections.push(new Paragraph({
children: [new TextRun({
text:
`// 플레이어 액티브 → 적
EnemyHPResult = EnemyHP - (
ActiveBaseDamage
× CardMultiplier (1.0~2.5)
× StackLevelFactor (Lv.1=1.0 / Lv.2=1.2 / Lv.3=1.4 / Lv.4=1.6 / Lv.5=2.0)
× AttributePassiveBonus (P02~P05 속성 강화 보유 시, 1.0~1.5)
)
// 각성 발동 시
EnemyHPResult = EnemyHP - (AwakeningBaseDamage × CardMultiplier × AttributePassiveBonus)
// AwakeningBaseDamage = Lv.5 액티브 대비 2~3배
// 적 → 플레이어
PlayerHP -= EnemyATK (쿼터 단위 차감, i-frame 내 피격 무효)
// 최대 하트 수 × 4 쿼터 = 총 HP`,
font: 'Consolas', size: 18,
})],
spacing: { after: 200, line: 280 },
}));
sections.push(para('단순성이 설계 의도다. 방어 수치(DEF)는 도입하지 않으며, 패시브 [방어] 카드의 피해 감소 %가 그 역할을 대체한다.', { italics: true }));
// === §7 진행 시스템 ===
sections.push(h1('7. 진행 시스템 (3축 육성)'));
sections.push(para('EerieVillage의 육성 축은 3종이며, 각 축은 손실 범위가 다르게 설계되어 플레이어의 리스크 인지와 감정 곡선을 층화한다.'));
sections.push(makeTable(
['축', '획득 시점', '사망 시 처리', '재미 기여'],
[
['A. 스킬 카드', '런 내 레벨업', '전손', '즉시 육성 · 빌드 실험 · 낙차 핵심'],
['B. 아이템', '런 내 드롭', '유지', '준영속 기반 · 축적된 발자취'],
['C. 특성', '메타 누적', '유지', '영속 성장 · 도전 지속성'],
],
[1700, 2300, 1500, 3860],
));
sections.push(h2('7.1 축 A — 스킬 카드'));
sections.push(bullet('§5 카드 시스템 본문 참조. 레벨업 시 3장 중 1장 선택 강제, 동일 카드 재픽으로 Lv.5까지 스택.'));
sections.push(bullet('태그 기반 시너지 — 동일 태그 K장 이상 빌드 편입 시 패시브 효과 추가 발동. K 임계값과 효과 강도는 밸런스 영역.'));
sections.push(h2('7.2 축 B — 아이템 (파츠 1개 교체식)'));
sections.push(bullet('전투 중 아이템 드롭 → 동일 파츠 기존 장착 시 교체 또는 포기 선택.'));
sections.push(bullet('장착 아이템은 사망 후에도 유지된다.'));
sections.push(bullet('파츠별 1개 제한으로 재화·슬롯 팽창을 방지하고 선택 압박을 유지.'));
sections.push(h2('7.3 축 C — 특성 (영속 성장)'));
sections.push(bullet('특정 조건 충족 시 특성 획득 (조건은 후속 단계에서 확정 — 메타 재화·보스 처치·업적 등 옵션).'));
sections.push(bullet('특성은 사망·레벨 초기화에도 유지되며, 신규 런 시작 시 자동 적용된다.'));
sections.push(bullet('축 C는 "하한 상승"이 아니라 "도전 지속성" 제공이 본질 — 강해지는 느낌과 동시에 더 깊은 스테이지 도전 유도.'));
sections.push(h2('7.4 3축 상호 관계'));
sections.push(new Paragraph({
children: [new TextRun({
text:
`축 A (카드) — 단기 쾌감 (런 내 폭발·전손)
↓ 영향
축 B (아이템) — 중기 기반 (런 간 유지·발자취)
↓ 영향
축 C (특성) — 장기 성장 (영속·도전 확장)`,
font: 'Consolas', size: 18,
})],
spacing: { after: 200, line: 280 },
}));
sections.push(bullet('축 A의 전손은 축 C가 있기에 절망이 아니라 "다시 빌드할 준비"로 느껴진다.'));
sections.push(bullet('축 B는 "이번 런은 실패했지만 아이템은 남았다"는 감정의 안전판.'));
sections.push(bullet('축 C는 "여러 런 누적이 의미 있다"는 거시 동기.'));
// === §8 스테이지 구조 ===
sections.push(h1('8. 스테이지 구조'));
sections.push(h2('8.1 단일 스테이지 3단 구성'));
sections.push(new Paragraph({
children: [new TextRun({
text:
`[입장]
▼
[구간 1: 도입] ← 빌드 시드 형성
- 약한 적 중심
- 기본 플랫폼 지형
- 1~2회 레벨업 예상
▼
[구간 2: 전개] ← 빌드 확장
- 중간 강도 적 · 엘리트 1~2기
- 점프 퍼즐 1~2개
- 2~3회 레벨업 예상
- 아이템 드롭 기회 중심
▼
[구간 3: 보스 방] ← 빌드 검증
- 보스 (전용 지형, 고정 카메라 권장)
- 진입 시 후방 차단
- 처치 후 보상 → 분기 선택: 마을 복귀 / 다음 스테이지`,
font: 'Consolas', size: 18,
})],
spacing: { after: 200, line: 280 },
}));
sections.push(h2('8.2 보스 방 설계 원칙'));
sections.push(bullet('진입 시 후방 차단으로 긴장 집중.'));
sections.push(bullet('고정 카메라로 횡스크롤 해제 후 아레나 모드 (연출상 임팩트).'));
sections.push(bullet('가독성 높은 텔레그래프 의무 — "랜덤 사망" 방지로 축 2 재미 보호.'));
sections.push(bullet('보스 1종 고정 (페이즈 구조로 깊이 확보). 다수 보스 동시 출현 금지.'));
sections.push(h2('8.3 난이도 곡선 — 레벨업 빈도와 보스 TTK'));
sections.push(makeTable(
['스테이지 종료', '예상 누적 XP', '예상 레벨', '보유 카드 수 (액티브 + 패시브)'],
[
['Stage 1', '~292', 'Lv 3~4', '3~4장'],
['Stage 2', '~584', 'Lv 5~6', '5~6장'],
['Stage 3', '~876', 'Lv 6~7', '6~7장'],
['Stage 4', '~1168', 'Lv 7~8', '7~8장'],
['Stage 5', '~1460', 'Lv 8~9', '8~9장'],
],
[2300, 1900, 1900, 3260],
));
sections.push(para('각성 발동 기대치: Stage 3~4 구간에서 첫 각성 조건 충족 가능 (액티브 Lv.5 도달 + 필요 패시브 1개 + 보물상자 획득).'));
sections.push(para('보스 TTK 목표: 50~90초 (캐주얼 5~10분 런의 15~20% 시간). 빌드 없는 초반 약 75초, 카드 2~3장 빌드 후 약 50초.'));
sections.push(h2('8.4 적 등급 체계 (초안)'));
sections.push(makeTable(
['등급', 'HP', 'ATK (쿼터 피해)', '쿨다운', '이동 속도', '비고'],
[
['일반 적 (약)', '40', '1', '1.2 s', '2.0 m/s', '첫 구간 전용. 3~4타 처치'],
['일반 적 (중)', '60', '1~2', '0.9 s', '3.0 m/s', '구간 2 주력'],
['엘리트', '120', '2', '0.7 s', '3.5 m/s', '구간 2 후반~보스 전'],
['보스 페이즈 1', '400', '2~3', '1.5 s', '2.5 m/s', '스테이지 보스'],
['보스 페이즈 2', '(HP 50% 이하)', '3~4', '1.2 s', '3.0 m/s', '위험 구간'],
],
[1900, 1100, 1900, 1100, 1300, 2060],
));
// === §9 모바일 UX ===
sections.push(h1('9. 모바일 UX'));
sections.push(h2('9.1 조작 스킴 (VS 순수형)'));
sections.push(new Paragraph({
children: [new TextRun({
text:
`┌──────────────────────────────┐ ← 화면 상단 (HUD 영역)
│ [HUD] │
├──────────────────────────────┤
│ │
│ 플레이 영역 │
│ │
├────────────┬─────────────────┤
│ [가상스틱] │ [점프] │ ← 입력 영역 (공격 버튼 없음)
│ 왼손 엄지 │ 오른손 엄지 │
└────────────┴─────────────────┘
Safe Area (Home Indicator 회피)`,
font: 'Consolas', size: 18,
})],
spacing: { after: 200, line: 280 },
}));
sections.push(bullet('가상 스틱 반지름 60dp 후보. 조이스틱 중심은 터치 다운 위치 추종.'));
sections.push(bullet('점프 버튼은 우측 중앙 단독 대형 배치 (시인성·터치 성공률).'));
sections.push(bullet('입력 영역 투명도 70% / 입력 시 100%. Safe Area 패딩 의무.'));
sections.push(bullet('Input 감지 후 0.1초 이내 캐릭터 반응 의무 — 지연 시 입력 불인식 오인.'));
sections.push(h2('9.2 인게임 HUD'));
sections.push(makeTable(
['우선순위', '요소', '이유'],
[
['1', '하트 UI (생존 여부 + 잔량)', '하트 분할 → 쿼터 단위 잔량 즉시 인지 필수'],
['2', '레벨 + 경험치 게이지', '레벨업 카드 픽 트리거 예고'],
['3', '액티브 슬롯 (장착 무기 + Lv 표기)', '자동 발동 감상 재미의 기준 정보'],
['4', '패시브 슬롯 (장착 패시브 + Lv 표기)', '빌드 확인용. 전투 흐름 방해 금지'],
['5', '각성 조건 진행도', '액티브 Lv.5 도달 시 "각성 대기" 표시'],
],
[1300, 3700, 4360],
));
sections.push(h3('HUD 와이어프레임'));
sections.push(new Paragraph({
children: [new TextRun({
text:
`┌──────────────────────────────┐
│ [Lv.3 ████████░░] [♥ ♥] │ ← 좌상단: 레벨·경험치 + 하트 분할 UI
│ [⚙] │ ← 우상단: 일시정지
├──────────────────────────────┤
│ 플레이 영역 │
├────────────┬─────────────────┤
│ 액티브: │ 패시브: │ ← 하단: 카드 슬롯 분리 (반투명)
│ [A1][A2] │ [P1][P2][P3] │
│ [A3][★★] │ [P4][P5][P6] │ ← ★ = 각성 대기
└────────────┴─────────────────┘`,
font: 'Consolas', size: 18,
})],
spacing: { after: 200, line: 280 },
}));
sections.push(h2('9.3 레벨업 카드 픽 UI'));
sections.push(bullet('트리거: 경험치 만렙 → Time.timeScale = 0 일시정지 → 카드 픽 화면 진입.'));
sections.push(bullet('Canvas: CardPickCanvas.prefab (Additive Load), Unscaled Time 사용으로 timeScale 0에서도 정상 동작.'));
sections.push(bullet('각 카드 상단에 액티브·패시브 분류 아이콘 명시 (색상·기호) — "어떤 슬롯으로 들어갈 카드인가" 즉시 인지.'));
sections.push(bullet('이미 장착한 카드는 "Lv.N → Lv.N+1" 표기, 미장착은 "신규" 표기.'));
sections.push(h2('9.4 피드백 — 피해량별 차등'));
sections.push(makeTable(
['피해량', '진동 (모바일)', '시각 피드백'],
[
['1 (1 쿼터)', '짧은 진동 40ms', '테두리 연한 섬광'],
['2 (반 하트)', '중간 진동 80ms', '테두리 중간 섬광'],
['3 (3/4 하트)', '긴 진동 120ms', '테두리 강한 섬광'],
['4 (하트 전소)', '강한 진동 160ms', '테두리 최대 섬광 + 화면 살짝 흔들림'],
],
[2300, 3300, 3760],
));
// === §10 향후 계획 ===
sections.push(h1('10. 향후 계획'));
sections.push(h2('10.1 PD 후속 검토 영역'));
sections.push(numbered('BM · 과금 구조 — 인앱 결제 모델, 광고 도입 여부, 유료 재화 설계.'));
sections.push(numbered('아트 톤 · UI 톤 — 일러스트 방향성, UI 컬러 팔레트, 폰트, 마을·스테이지 배경 비주얼 가이드.'));
sections.push(numbered('퇴마사 고유 이름 확정 — 현재는 "유저 자기투영" 보존을 위해 미정. 시나리오 대본 단계에서 결정.'));
sections.push(numbered('태그 세계관 재매핑 — 일반 RPG 용어 11종(물리/화염/냉기/번개/암흑/근접/원거리/범위/지속/회복/방어)을 조선 퇴마 특화 용어로 일괄 재매핑 (시나리오 영역).'));
sections.push(numbered('출시 일정 · 빌드 마일스톤 — 현 시점 미정.'));
sections.push(h2('10.2 코어 프레임워크 (BT.Framework)'));
sections.push(para('BurningTimes 조직의 자산인 BT.Framework Tier 1 16종이 본 프로젝트에서 1순위 도입 검토 대상이다.'));
sections.push(bullet('Tier 1 즉시 활용: SafeAreaBorder, Log, ValidationEx, FormatEx, EnumEx, MathEx 등.'));
sections.push(bullet('Tier 2 신규 구현 후보: UITouchHandler (가상 스틱 멀티터치), BackKeyDispatcher (Android 뒤로가기 통합).'));
sections.push(bullet('Tier 3 (전투·네트워크·UI 고급)은 본작 기획 확정 후 재평가.'));
sections.push(h2('10.3 검증 시나리오 (밸런스)'));
sections.push(makeTable(
['ID', '시나리오', '기대 결과'],
[
['V-1', '일반 적(약) 1vs1 교전', '액티브 자동 발동 3~4타 처치, 피격 시 1/4 하트 감소'],
['V-2', '피격 직후 연속 히트', 'i-frame 0.6초 내 2번째 적 공격 무효'],
['V-3', '하트 분할 시각화', 'ATK 1 피격 시 풀 하트 → 3/4 하트 전환 표시'],
['V-4', '최대 하트 수 증가', 'P15 생명의 꽃 Lv.1 획득 시 최대 HP 4 → 8 쿼터 변환'],
['V-6', '보스 TTK 상한', '카드 0장 기준 보스 HP 400 → DPS 기준 75~100초'],
['V-7', '각성 발동 조건', '액티브 Lv.5 + 필요 패시브 1개 + 보물상자 획득 → 각성 발동'],
['V-8', '적 ATK 점진 강화', 'Stage 5 진입 시 일반 적 ATK 2 (반 하트) 확인'],
],
[800, 3500, 5060],
));
// === §11 부록 ===
sections.push(h1('11. 부록'));
sections.push(h2('11.1 변경 이력'));
sections.push(makeTable(
['일시', '단계', '주요 변경'],
[
['2026-04-23', 'v0.1 — 파일럿 초기 골격', '핵심 게임 룰 9개 기반 5종 골격 문서 작성 (게임 컨셉·코어 루프·진행 시스템·전투 스펙·스테이지 구조)'],
['2026-04-24', 'v0.2 — BT7-Plan 개정', 'PD 직접 지시 11건 반영. VS 순수형 (공격 버튼 제거), 액티브/패시브/각성 3분류, 하트 분할, 카드 50~65장 확장, Lv.5 스택, 보물상자 각성 트리거'],
['2026-04-24', 'v0.2 — BT11-Plan 60종 확장', '액티브 20 · 패시브 20 · 각성 20 컨셉 표 완비'],
['2026-04-26', 'v1 — 초기 기획서 통합', '본 문서. 16종 기획 SOT 통합 정리'],
],
[1300, 2700, 5360],
));
sections.push(h2('11.2 주요 기각안 요지'));
sections.push(para('본 절은 설계 과정에서 검토 후 기각된 안의 요지를 모아 둔다. 차후 같은 안건이 재논의될 때 "왜 이 방향을 선택하지 않았는지"를 빠르게 확인하기 위함이다.'));
sections.push(makeTable(
['영역', '기각안', '기각 사유'],
[
['게임 컨셉', '하드코어 로그라이크 포지션', '캐주얼 로그라이크 포지션 고수. 하드코어는 타겟 유저 확장 포기 의미'],
['게임 컨셉', '탑뷰 로그라이크 변형', '횡스크롤 플랫포머 확정. 템플릿(2D PlatformerMicrogame)과 정합'],
['전투', '수동 공격 유지 (액티브 + 수동 병행)', 'VS 순수형 명시. 수동 공격 병행은 복잡도 증가 + 자동 발동 감상 재미 저해'],
['전투', '4티어 레어리티 (Common/Uncommon/Rare/Epic)', '"액티브+패시브=각성" 3분류로 통일. 레어리티 체계 폐기'],
['전투', '적 ATK = 1 (즉사) 단일 설계', '하트 분할 + 점진 강화로 전환. 초반 관대·후반 가혹의 곡선 형성'],
['전투', 'i-frame 1.0초 / 0.3초', '1.0초는 보스 공격 대부분 무효화, 0.3초는 ATK 4 연타 위험. 0.6초 유지'],
['전투', 'DEF 스탯 도입', '패시브 [방어] % 감소로 역할 대체. 복잡도만 증가'],
['카드', '카드 합성 시스템 (2장 합쳐 상위 카드)', '동일 카드 스택 Lv.5가 합성의 재미를 단순 구조로 대체'],
['카드', '카드도 사망 후 일부 유지', '축 A 낙차가 없으면 재미 축 1 성립 불가. 카드 전손 고수'],
['카드', '각성을 레벨업 드로우 풀에 포함', '조건 미충족 각성 카드가 무의미 카드로 등장하여 픽 UX 저해. 별도 풀 + 보물상자 트리거'],
['진행', '카드 3픽이 아닌 2픽', '3이 선택 긴장·변동성·시너지 탐색의 최소 임계'],
['진행', '특성이 런 내에서도 증가', '축 C는 메타 영역. 런 내 증가 시 축 A와 역할 충돌'],
['스테이지', '완전 랜덤 프로시저럴 맵', '캐주얼 로그라이크에서 학습 곡선·제작 비용 과다. 부분 랜덤 중심 고정 맵'],
['스테이지', '보스 스킵 옵션', '"스테이지 마지막은 항상 보스" 고수. 보스가 빌드 검증·보상 분기의 핵심'],
['스테이지', '보스 여러 마리 동시 출현', '가독성 낮은 보스전은 축 2 붕괴 위험. 보스 1종 고정 (페이즈 구조로 깊이)'],
['세계관', '조선 고증형 리얼 세계관', '역사 오류 리스크 높고 고증 의무가 창작 자유 제한. 가상 역사 "요괴 성행기"'],
['세계관', '불교 중심 단일 퇴마 체계', '시각 언어가 절 배경으로 쏠림. 무속 중심 혼합 체계가 다양성 우위'],
['마을', '대규모 탐험형 마을', '마을 자체가 별도 게임 루프가 되어 재미 축 1·2를 분산. 선형 단층 마을 유지'],
],
[1500, 3500, 4360],
));
sections.push(h2('11.3 참조 문서 (내부 SOT)'));
sections.push(para('본 기획서는 다음 16종 SOT를 통합 정리한 것이다. 각 항목별 상세는 해당 원본 문서 참조.'));
sections.push(bullet('프로젝트/EerieVillage/기획/01_게임_컨셉.md (v0.2)'));
sections.push(bullet('프로젝트/EerieVillage/기획/02_코어_루프.md (v0.2)'));
sections.push(bullet('프로젝트/EerieVillage/기획/03_진행_시스템_초안.md (v0.1)'));
sections.push(bullet('프로젝트/EerieVillage/기획/04_전투_기본_스펙.md (v0.2)'));
sections.push(bullet('프로젝트/EerieVillage/기획/05_스테이지_구조_초안.md (v0.1)'));
sections.push(bullet('프로젝트/EerieVillage/기획/system/01_카드_시스템.md (v0.2)'));
sections.push(bullet('프로젝트/EerieVillage/기획/content/01_카드_풀.md (v0.2)'));
sections.push(bullet('프로젝트/EerieVillage/기획/content/02_스킬_효과_컨셉.md (v0.2)'));
sections.push(bullet('프로젝트/EerieVillage/기획/balance/01_전투_수치.md (v0.2)'));
sections.push(bullet('프로젝트/EerieVillage/기획/balance/02_레벨업_곡선.md (v0.2)'));
sections.push(bullet('프로젝트/EerieVillage/기획/ux/01_모바일_터치_UX.md (v0.2)'));
sections.push(bullet('프로젝트/EerieVillage/기획/ux/02_HUD_설계.md (v0.2)'));
sections.push(bullet('프로젝트/EerieVillage/기획/narrative/01_세계관_SOT.md (v0.1)'));
sections.push(bullet('프로젝트/EerieVillage/기획/narrative/02_보스_네이밍.md (v0.1)'));
sections.push(bullet('프로젝트/EerieVillage/기획/narrative/03_마을_컨셉.md (v0.1)'));
sections.push(h2('11.4 작성 정보'));
sections.push(bullet('작성: BurningTimes Studio 기획팀장'));
sections.push(bullet('작성일: 2026-04-26'));
sections.push(bullet('대상: 프로듀서·디렉터(PD), 외부 공유 가능'));
sections.push(bullet('단계: Phase 3-A·B 통합 정리. Phase 3-C(BM·아트 톤·세부 대본)는 후속 단계 이관.'));
// === Document ===
const doc = new Document({
creator: 'BurningTimes Studio · 기획팀',
title: '기묘한 고을 : 조선퇴마뎐 — 초기 기획서 v1',
description: 'EerieVillage: Joseon Exorcist — Initial Design Document v1',
styles: {
default: {
document: { run: { font: FONT_KO, size: 22 } },
},
paragraphStyles: [
{
id: 'Heading1', name: 'Heading 1', basedOn: 'Normal', next: 'Normal', quickFormat: true,
run: { size: 36, bold: true, font: FONT_KO_HEAD, color: '1F3864' },
paragraph: { spacing: { before: 360, after: 240 }, outlineLevel: 0 },
},
{
id: 'Heading2', name: 'Heading 2', basedOn: 'Normal', next: 'Normal', quickFormat: true,
run: { size: 28, bold: true, font: FONT_KO_HEAD, color: '2E75B6' },
paragraph: { spacing: { before: 280, after: 160 }, outlineLevel: 1 },
},
{
id: 'Heading3', name: 'Heading 3', basedOn: 'Normal', next: 'Normal', quickFormat: true,
run: { size: 24, bold: true, font: FONT_KO_HEAD, color: '375E97' },
paragraph: { spacing: { before: 200, after: 120 }, outlineLevel: 2 },
},
],
},
numbering: {
config: [
{
reference: 'bullets',
levels: [
{
level: 0, format: LevelFormat.BULLET, text: '•', alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 540, hanging: 270 } } },
},
{
level: 1, format: LevelFormat.BULLET, text: '◦', alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 1080, hanging: 270 } } },
},
],
},
{
reference: 'numbers',
levels: [
{
level: 0, format: LevelFormat.DECIMAL, text: '%1.', alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 540, hanging: 270 } } },
},
],
},
],
},
sections: [
{
properties: {
page: {
size: { width: 12240, height: 15840 }, // US Letter
margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 },
},
},
headers: {
default: new Header({
children: [new Paragraph({
alignment: AlignmentType.RIGHT,
children: [new TextRun({ text: '기묘한 고을 : 조선퇴마뎐 — 초기 기획서 v1', font: FONT_KO, size: 18, color: '808080' })],
})],
}),
},
footers: {
default: new Footer({
children: [new Paragraph({
alignment: AlignmentType.CENTER,
children: [
new TextRun({ text: 'BurningTimes Studio · 기획팀 | ', font: FONT_KO, size: 18, color: '808080' }),
new TextRun({ text: '', font: FONT_KO, size: 18, color: '808080', children: [PageNumber.CURRENT] }),
new TextRun({ text: ' / ', font: FONT_KO, size: 18, color: '808080' }),
new TextRun({ text: '', font: FONT_KO, size: 18, color: '808080', children: [PageNumber.TOTAL_PAGES] }),
],
})],
}),
},
children: sections,
},
],
});
const outPath = path.join(__dirname, '기묘한고을_초기기획서_v1.docx');
Packer.toBuffer(doc).then(buffer => {
fs.writeFileSync(outPath, buffer);
const stats = fs.statSync(outPath);
console.log('OK ' + outPath);
console.log('Size: ' + (stats.size / 1024).toFixed(1) + ' KB');
}).catch(err => {
console.error('FAIL', err);
process.exit(1);
});

File diff suppressed because it is too large Load Diff