// 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); });