Chaosforge — 레벨링·경제·속성 설계서
Phase 1 구현 전 확정 스펙. 모든 수치는
shared/data/+shared/src/balance/에 데이터로만 존재하며, 코드에 매직넘버를 두지 않는다.
0. 설계 원칙 & 학술·업계 참고
참고 문헌
| 출처 | 핵심 인사이트 | 본 게임 적용 |
|---|---|---|
| Unlimited Rulebook (URB) — Mizutani & Kon, IEEE ICSA 2020 (로컬 PDF) | 로그라이크·덱빌딩의 경제 메카닉은 규칙이 자주 바뀌므로 ECS + Predicate Dispatch + 데이터 주도 규칙 엔진이 유리 | shared의 applyRule(context, event) 패턴, 아이템·시너지·속성을 규칙 테이블로 선언 |
| Economy Mechanics Reference Architecture — SBGames 2019 (로컬 PDF) | 게임 내 경제는 예측 불가·불안정 → 아키텍처로 복잡도 격리 | 골드·상점·드랍·메타 재화를 EconomyGraph 노드로 모델링, 시뮬로 검증 |
| GEEvo — Rupp & Eckert, IEEE CEC 2024 (로컬 PDF · arXiv) | 경제를 방향 그래프로 두고 시뮬 fitness로 밸런스 | CI에서 simulateRun(seed×N) → 층별 생존률·골드 잔액 분포가 목표 밴드 안인지 검사 |
| Rock-Paper-Scissors in JRPG — Game Developer (기사) | 속성 상성은 비가환(non-transitive) 순환으로 전략 깊이 제공 | 5원소 통제 사이클 + 직업별 편향 |
| Elemental weakness riders — GameDev StackExchange / Persona류 설계 | 약점은 데미지 배율만이면 단조로움 → 상태이상 라이더 병행 | Weak 시 디버프 부여 (Burn, Chill, Root 등) |
| Difficulty curve — abagames sqrt 곡선 (문서) | 초반 급격·후반 완만한 √ 또는 segmented linear | 층 스케일은 floor^0.65 계열 + 보스 스파이크 |
| BL3 9% per level — 커뮤니티 역산 (MP1st) | 지수 스케일은 장비 수명이 너무 짧아짐 → 완만한 지수(1.07~1.09) | 아이템 티어 스탯은 base × 1.08^(tier-1) |
설계 금지 사항
- 층마다 선형
+35%같은 단일 계수만 쓰지 않는다. - 속성은 Rock-Paper-Scissors 3각만으로 끝내지 않는다 (빌드 다양성 붕괴).
- 골드 인플레이션을 막는 싱크(sink) 없이 보상만 늘리지 않는다.
- UI 문자열 하드코딩 금지 — i18n 키만 사용.
0.1 Grid-First (배낭 우선)
상세 로어·매핑: DESIGN.md §코어 루프
| 원칙 | 스펙 |
|---|---|
| 전투력 예산 | 배낭 배치 ≥80% · 포지션·축복 스탯 ≤15% · 메타 ≤5% |
| 1런 주 동사 | 소환진 구매·배치·머지·재배치 (응결·스탯 클릭은 보조) |
| 응결 | 오클 수입만. 빌드 표현 축 아님 → 소환진에서 조각 구매 |
| 포지션 | 가방 크기·인접·활성화 규칙 우선. flat ATK/DEF 보정 최소화 |
| 오파츠 | 무형 패시브 금지. 큰 shape + 인접 룰 변경 |
| 내구 | 세금이 아닌 레이아웃 붕괴 — Broken 시 시너지 재계산 |
| 소환진 UX | 구매 후 즉시 배낭 배치. stashCells 제한 (기본 4칸) |
| 시뮬 fitness | 동일 시드·층·오클에서 그리드 permutation별 승률 분산 검증 |
Phase 1a (갱신): 첫 시련 오클러 솔로(로컬 1–3 강제) → 허브에서 기사 무료 영입 → Vault 오클로 소집 풀 확장. 캐릭터별 개별 배낭(기본 4×4). battleSlots 4→6→8→10. 상세: LEVEL_DESIGN_RESEARCH.md.
1. 진행(Progression) 3층 구조
flowchart TB
subgraph meta [Meta_해금만]
ProtagonistLv[Commander_Level]
Unlock[Position_Party_Unlock]
ForgeMark[Sigils_포지마크]
end
subgraph prerun [Trial_Start_시련시작]
Roster50[Roster_~50]
BattlePick[Battle_Pick_4-10]
ChapterPick[Trial_Chapter_1-100]
end
subgraph run [InRun_시련전체]
ShopRegen[Shop_Phase_Ochl_Regen]
OchlReserve[Ochl_Reserve]
Durability[Artifact_Durability]
Floor[LocalFloor_1-10]
end
meta -->|해금| prerun
prerun --> run
ShopRegen --> OchlReserve
OchlReserve --> Durability
Floor --> ShopRegen
| 층 | 범위 | 플레이어 체감 | 영속 |
|---|---|---|---|
| In-Run | 1시련 3~8분, 로컬 층 1~10 | 오클·내구·상점·빌드 전부 여기 | X (매 시련 리셋) |
| Item | 티어·희귀도 | 배치·머지·마모 | 시련 내 |
| Meta | 해금·포지 마크 | 다음 시련 시작 옵션만 | O (스탯 인플레 최소) |
원칙: 아티팩트 내구·오클 수급·상점 보충은 메타가 아님. 시련 끝나면 배낭·내구·Reserve 전부 소멸.
메타 파워 인플레이션 방지: 해금은 포지션·파티 슬롯·도감. 전투 스탯 보너스 +8% 이내 (Lv30).
1.5 허브 · 소집(Roster) · 유휴 오클
로어: DESIGN.md §소집·§봉인의 탑
오클 = 시련 에너지 + 화폐 + 전투 연료.ochlReserve ≤ 0→ 상점·충전 등 soft-lock. 시련 패배는 소대 전멸만 (squadHp ≤ 0). 오클 고갈 ≠ 패배.
1.5.1a 전투 슬롯 해금
battleSlots(L) =
L < 6 ? 4 :
L < 14 ? 6 :
L < 24 ? 8 : 10
| 지휘관 Lv | BATTLE_SLOTS |
|---|---|
| 1–5 | 4 |
| 6–13 | 6 |
| 14–23 | 8 |
| 24+ | 10 |
- 시련 시작 시 스냅샷 — 런 중 변경 없음.
- 구현:
battleSlots(Lv)표 적용. 첫 시련 솔로 → 허브 오클 영입(기사·마법사·키메라). 오클러·메그넘은 전직(잠정). - 복잡도: 멤버당 배낭은 작게 고정(4×4)·루프 동일. 늘어나는 건 관리할 배낭 개수와 Trial Prep 선택지뿐.
1.5.1b 소집 · 시련 소대
| 필드 | 권장값 | 비고 |
|---|---|---|
ROSTER_MAX |
50 | 허브 소집 풀 |
BATTLE_SLOTS |
4 → 6 → 8 → 10 | 지휘관 Lv 해금 (§1.5.1a) |
| 주인공 필참 | 없음 | ochler 0~`BATTLE_SLOTS` |
| 중복 | 동일 allyId 불가 |
type RosterMember =
| { kind: 'ochler'; allyId: string; mageTalent: MageTalentTier }
| { kind: 'mage'; allyId: string }
| { kind: 'knight'; allyId: string }
| { kind: 'chimera_sage'; allyId: string }
| { kind: 'magnum'; allyId: string };
type HubState = {
roster: RosterMember[]; // length ≤ ROSTER_MAX
vault: number;
vaultCap: number;
lastRegenAt: number;
status: 'idle' | 'in_trial';
};
type TrialSquad = {
battle: RosterMember[]; // length ≤ BATTLE_SLOTS, subset of roster
ochlReserve: number;
satchels: Record<string, BackpackGrid>; // key = member id, 공유 없음
};
1.5.2 패배 조건 (시련)
| 조건 | UI |
|---|---|
| 소대 HP 전멸 | ui.resultDefeat — 전멸 (유일한 시련 패배) |
ochlReserve ≤ 0 |
패배 아님 — 상점·충전 soft-lock, 시련 계속 (ui.ochlDepletedHint) |
| (선택) 배낭 과부하 | 전투 시작 시 activationCost 합 > ochlReserve → 시작 불가 (상점에서 해결) |
1.5.3 잃어버린 마법 재능 (mageTalent) — 오클러만
오클러가 마법사가 되었을 잠재 — 생산량만 반영. 시련 중 마법 사용 불가.
| id | EN | 로어 | 생산 배수 |
|---|---|---|---|
talent.ash |
Ash | 마법 소질 거의 없음 | 0.6× |
talent.ember |
Ember | 평범한 마법사 잠재 | 1.0× |
talent.flare |
Flare | 유망한 마법사 | 1.5× |
talent.nova |
Nova | 대마법사급 잠재 | 2.2× |
- 동료 오클러: 고용 시
mageTalent롤 - 특수 오클러(구 주인공):
talent.nova+PROTAGONIST_OCHL_MULT = 3.5— 로스터 1명일 뿐, 필참 아님
1.5.4 유휴 충전 (Idle Regen)
조건: status === 'idle'. 소집 풀 내 모든 오클러가 합산.
틱당 생산량:
ochlPerTick = sum over roster where kind === 'ochler':
BASE_UNIT × talentMult(m.talent) × (m.isProtagonistTier ? PROTAGONIST_OCHL_MULT : 1)
BASE_UNIT = 1(밸런스 기준점,economy.ts데이터화)- 오프라인:
lastRegenAt이후 경과 틱만큼 일괄 정산 (상한vaultCap)
Vault 상한:
vaultCap(L, ochlerCount) = 10 + 6×L + 4×ochlerCount
// ochlerCount = roster 내 ochler 수 (특수 오클러 포함)
1.5.5 수익 증대 요약
| 플레이어 행동 | 효과 |
|---|---|
| 오클러 다수 소집 | 유휴 ochlPerTick ↑ · 시련 응결 가중치 ↑ |
| 오클러 0명 시련 | 응결 0 · 마법 증폭 불가 · 배낭·개인스킬만 |
| 기사·마법사·메그넘 | 전투 스킬 + 호환 배낭 유물 |
1.5.6 시련 입장 · 런 연결
| 단계 | 오클 흐름 |
|---|---|
| 입장 | trialEntryCost(L) = 10 + floor(L / 2) 를 Vault에서 차감 |
| 런 시작 | ochlReserve = min(vaultAfterCost, carryCap(L)) — 일부만 배낭에 실음 |
carryCap(L) |
15 + L (시련 중 들고 갈 최대) |
| 런 중 | 기존 §2·§6 — 소환진·활성화·층 보상 |
| 런 종료 | 남은 ochlReserve 100% Vault 환급. 오클 지갑에 봉인한 분도 100% — SHOP_DESIGN.md |
| 상태 | in_trial 동안 유휴 충전 정지 |
1.5.7 구현 단계
| Phase | 범위 |
|---|---|
| 1a | 런 내 gold만, 오클러 1 암시적, 소대 미구현 |
| 1c | Trial Prep (4~10슬롯), 전멸 패배 · 오클0 soft-lock |
| 2 | Roster 50, Hub, Idle Regen |
1.6 시련 챕터 · 승리 조건
1회 시련 = 로컬 10층.
장기: 챕터 100 × 10 = 글로벌 1000층.
EA 기준: 챕터 I–X = 글로벌 1–100층.
마스터 기획: CHAPTERS_10_PLAN.md.
구현 현황: 런타임TrialChapter = 1 \| 2 \| 3(I–III).
1.6.1 챕터 구조
| 범위 | 챕터 | 글로벌 | 해금 |
|---|---|---|---|
| 지금 | I–III | 1–30 | I 기본 · 직전 클리어 |
| EA | I–X | 1–100 | 직전 클리어 (+ Lv 소프트) |
| 장기 | XI–C | 101–1000 | 포스트 EA Arc (100층 단위) |
// 장기 목표 타입; EA 콘텐츠 캡 = 10
type TrialChapter = number; // 1..100
globalFloor(chapter, localFloor) = (chapter - 1) * 10 + localFloor;
시련 시작 시 해금된 챕터 1개 선택. 런 중 챕터 변경 없음. 바이옴·보스: CHAPTERS_10_PLAN.
1.6.2 보스 · 인장 (챕터당)
| 로컬 층 | 역할 |
|---|---|
| 5 | 미니 보스 + Stratum Seal 1 |
| 10 | 챕터 보스 — 클리어 = 시련 승리 + Seal 1 |
- 챕터 X F10 = EA 100층 캡 클리어.
- 챕터 C (100) F10 = 로드맵상 마지막 밴드 클리어 (종결 엔딩·「탑 완전 봉인」 없음).
1.6.3 승리 · 패배 · 점수
| 결과 | 조건 |
|---|---|
| 시련 클리어 | 선택 챕터 로컬 10층 보스 처치 |
| 패배 | squadHp ≤ 0 (소대 전멸). ochlReserve ≤ 0은 패배 아님 |
| 중도 퇴각 | (Phase 3+) — 런치 미포함 |
score = globalFloorReached × 1000 + ochlRemaining × 5 + (cleared ? 5000 : 0)
- 포지 마크: 런 종료
globalFloorReached × 1(클리어 ×2), 일일 첫 클리어+5 - 리더보드: 챕터별
score· 클리어 타임 - 지휘관 XP:
globalFloorReached × 50 + score / 100
1.6.4 엔드 이후
- EA: Ch.X 클리어 후 심층(3챕터 연쇄) · Ch.XI 티저.
- 장기: Arc 확장 · 1000층 챌린지. Ch.C도 일반 챕터 클리어와 동일. 상세: CHAPTERS_10_PLAN §5–6
2. 포지션 · 시련 소대
소집 ~50 중 전투 4~10 선발 (
battleSlots(Lv)). 포지션 = 인원 역할(kind).
2.1 개요
| 개념 | 코드 | 설명 |
|---|---|---|
| 소집 풀 | hub.roster |
≤ 50 |
| 시련 소대 | trial.battle |
≤ battleSlots(Lv) |
| 오클러 | kind: 'ochler' |
응결·오클 공급. 0명 가능 |
| 배낭 | RunState.grids[memberId] |
캐릭터별 개별 그리드 (공유 없음), 포지션별 기본 장비로 시작 |
| 유물 호환 | ItemDef.compatiblePositions |
배치 유물이 적용될 소대 역할 |
type PositionId =
| 'ochler'
| 'mage'
| 'knight'
| 'chimera_sage'
| 'magnum';
// assassin 폐기 → magnum + mage(wind) 흡수
// RosterMember.kind 와 1:1. 시련 소대는 RosterMember[] 부분집합.
2.2 전투 중 오클 흐름
// 전투 종료 (승·패 공통)
ochlReserve -= sum(ochlChargeCost per satchel item) // 마법사 배낭은 할인 적용
// 전투 종료 (승리)
ochlReserve += condense(spillOd, ochlers in squad) // 오클러 0이면 +0
// 전투 종료 (패배)
ochlReserve unchanged
자체 마력 vs 오클: skillManaMax는 포지션 스킬 전용 풀(기사·마법사). ochlReserve는 아이템 충전·상점·응결용 — 틱마다 깎지 않음.
2.3 역할별 — 시련 규칙
ochler (오클러)
| 항목 | 값 |
|---|---|
| 개인 스킬 | 없음 |
| 응결 | spillOd × talentMult 가중치 합산 |
| 배낭 | 활성화 비용 공급만 |
mage (마법사)
| 항목 | 값 |
|---|---|
| 자체 마력 | skillManaMax: 5 — 스킬 전용, 오클과 분리 |
| 패시브 | 자기 배낭 아이템 오클 충전량 −1○ (ochlChargeDiscount) |
| 개인 스킬 | 속성 마법 — 마력 소모 (§3, Phase 2 채널) |
| 배낭 | accessory 태그 보정 |
knight (기사)
| 항목 | 값 |
|---|---|
| 자체 마력 | skillManaMax: 3 — 스킬 전용 |
| 개인 스킬 | 보루(자신의 방패 발동 시 어그로 스택 +1) — 가로채기는 방패 아이템 공통 |
| 배낭 | shield/armor/sword 태그 보정 |
magnum (메그넘) — Phase 2
| 항목 | 값 |
|---|---|
| 설정 근거 | 키메라 술사가 결합한 신체형 오파츠. 구 암살자 전투 니치 |
| 체형 슬롯 | 2×2 고정, origin: oopart, originSubtype: body |
| 개인 스킬 | 전투 첫 3틱 SPD +50%, Weak 시 expose 라이더 확률 ↑, 오파츠 proc |
| 배낭 | dagger/wind 호환 유물 → 메그넘에 적용 (체형과 중첩 가능) |
| 특수 | 체형 오파츠 onTick/proc 항상 발동 |
chimera_sage (키메라 술사) — Phase 2
| 항목 | 값 |
|---|---|
| 설정 근거 | 하베르트 계열 봉인 키메라 조종 |
| 개인 스킬 | 후방 지원·소환 시전 (약한 본체 ATK) |
| 배낭 | chimera_orb 태그 유물 — 배치 = 소환 준비 |
| 소환 | 전투 시작 시 배치된 오브 1개당 키메라 1체 (§4.1c) |
| 조건 | 소대에 술사 없으면 오브 비활성 |
| 획득 | event.chimera_capture · 보스 · 축복 (상점 X) |
2.4 편성 규칙
| 규칙 | 내용 |
|---|---|
| 소집 | ≤ 50 |
| 시련 소대 | ≤ battleSlots(Lv) (4→6→8→10) |
| 오클러 | 0 ~ BATTLE_SLOTS |
| 중복 id | 불가 |
| UI | Hub Roster → Trial Prep → Run |
2.5 전투 시뮬 — 멀티 유닛 무기 발사 (구현됨, Phase 1a)
Grid-First 원칙 그대로, 계산 단위가 "소대 1블록"이 아니라 "유닛 하나하나·무기 하나하나"로 세분화됨. 유닛(캐릭터) 자체는 기본 공격이 없다 — 실제 데미지는 배낭 속 무기 아이템이 각자 자기 ATK·SPD·속성으로 독립 발사해서 낸다.
| 레이어 | 내용 |
|---|---|
| 유닛 방어 | computeUnitDefenses(grid, positionId, modifiers) — 그리드의 비무기(atk=0) 아이템 def/hp 합산 + 포지션 modifier → 유닛 def/hpMax |
| 유닛 무기 | computeUnitWeapons(grid) — 그리드의 무기(atk>0) 아이템을 개별 WeaponInstance로 추출(합산 안 함). 각자 max(1, 20-weapon.spd) 쿨다운으로 독립 발사 |
| 소대 구성 | computeSquadUnits(grids, squad, modifiers) — 멤버마다 위 둘을 합쳐 BattleUnit[] 생성 |
| 적 | getEnemiesForFloor(floor, chapter, seed) — 층당 1~3체(보스층 1체), 2체 이상은 enemyGroupStatMult로 개체당 스탯 완화 |
| 타겟팅 | 매 틱, 쿨다운이 찬 무기/적마다 상대 팀 중 현재 HP 최저 생존 유닛 공격 (동률은 배열 순서) |
| 오클러 | 전투 데미지 기여 없음 — 승리 후 응결만 (기존과 동일) |
// packages/shared/src/combat/types.ts (구현됨)
type BattleUnit = {
id: string;
hp: number;
hpMax: number;
def: number;
element?: Element;
weapons: readonly WeaponInstance[]; // 유닛 자체엔 atk/spd 없음
};
연출: 소대(좌) vs 적(우) 세로 대열, 유닛마다 HP 바·이름표. 무기별 투사체가 유닛→유닛으로 개별 비행(BattlePixi.ts).
연출 고도화 (구현됨 — Phase 1.5~2): 무기별
attackStyle투척(thrown) / 발사(shot) / 시전(cast) 3분류. 활·지팡이는 VFX 클립, 투척형만 아이콘 투사체.
상세:BATTLE_VFX.md§무기 공격 연출 ·WEAPON_DESIGN.md§15
전투 시작 가드: sum(activationCost, 전 멤버 그리드) > ochlReserve → 시작 불가 (Trial Prep에서 상점·재배치 유도).
Phase 2 범위(구현됨): 포지션 태그 보정·전열/후열·오클 충전(마법사 할인)·방패 가로채기·키메라 오브 소환·메그넘/오파츠·약점 라이더 — 상세 COMBAT_FORMATION.md. 미구현: 포지션 스킬 채널 UI·스킬별 마력 소모량.
2.6 배낭 = 캐릭터 소속 (구현됨)
배낭 자체가 이미 캐릭터 1인 소유이므로(§2.1), 과거 계획했던 "공유 그리드 + boundMemberId로 역할 전용 유물 바인딩" 방식은 불필요해져 폐기한다 — 어떤 아이템을 어느 멤버 그리드에 두느냐가 곧 소속이다.
| 항목 | 현재 |
|---|---|
| 그리드 소유 | grids[member.id] 1:1 — 다른 멤버 그리드에 못 둠 |
| 스태시 | stashes[member.id] — 상점 구매(buy 액션)에 memberId 지정, 그 멤버 스태시로만 들어감 |
| 인접 시너지 | 격자 위치 기준, 해당 멤버 그리드 내에서만 계산 (기존과 동일) |
PlacedItem.boundMemberId |
더 이상 필요 없음(그리드가 이미 소속을 나타냄) — 필드는 무해하므로 유지, 값은 항상 미사용 |
2.7 지휘관 레벨 (Meta) — 공적치
로어: 봉인의 탑 시련으로 쌓는 공적치 = 메타 경험치. 국가가 인정하면 허브 유휴 오클 세금이 줄어 vault 축적이 빨라진다. 만렙 = 유휴 완전 면세가 오클러의 목표. (시련 응결·보상은 면세)
전체 서사·용어: LORE_COMMANDER_MERIT.md
공적치 획득 (확정)
meritXp = (runBaseline + monsterMerit) × defeatMult
runBaseline = globalFloorReached × 12 + score / 450
monsterMerit = Σ baseMerit(tier) × (1 + localFloor/20) × fatigueRatio
defeatMult = 0.5 | 1.0
| 구성 | trash / elite / boss baseMerit | 비고 |
|---|---|---|
| runBaseline | — | 층·점수 — 주된 공적 |
| monsterMerit | 3 / 8 / 25 | 처치 보조 · 층 가중 · 감쇠 |
감쇠: 종족별 배율 — 처치마다 ×2/3, 하한 0.1, 선형 회복 +0.15/h. 패배 시 전체 50% (구출 비용). 상세: LORE §3.3.
- 레벨업 XP:
XP_req(L) = 175 × L^1.42(2026-07 — 초반 레벨업 완만화)
세금 감면 ↔ 경제 (구현됨 — 유휴만)
확정: 세금은 허브 유휴 생산(settleIdleOchl)에만 적용. 시련 응결·종료 vault 입금은 면세.
| 지휘관 Lv | 유휴 납부율 (예) | 게임 효과 |
|---|---|---|
| 1 | 90% | vault에 유휴 생산의 **10%**만 적립 |
| 중간 | 공적에 따른 감면 | taxRate(Lv) 하락 · carryCap·vaultCap 상승 (아래 표) |
| 30 | 0% | 유휴 100% vault |
시련 중 ochlReserve 증가(응결) 및 시련 후 vault 귀환: 세금 0%.
구현: taxRate(commanderLevel) · settleIdleOchl · depositTrialSpoilsToVault(면세).
| 효과 | per level | Lv30 합 |
|---|---|---|
regenIntervalSec |
−8초 (하한 60초) | 300→60초 |
vaultCap |
+6 | +180 |
carryCap |
+1 | +30 |
trialEntryCost |
+0.5 (반올림) | +15 |
시련 전투 소폭 보너스 (인플레이션 캡 — 선택)
| 스탯 | per level | Lv30 합 |
|---|---|---|
| HP | +2 | +60 |
| ATK | +0.5 | +15 |
| DEF | +0.3 | +9 |
우선은 세금·슬롯·carry만 적용하고 전투 스탯 보너스는 보류 권장.
해금 테이블
| 지휘관 Lv | 해금 |
|---|---|
| 1 | 허브 · 기사 · BATTLE_SLOTS 4 · 챕터 I |
| 5 | 마법사 |
| 6 | BATTLE_SLOTS 6 |
| 12 | 키메라 술사 |
| 14 | BATTLE_SLOTS 8 |
| 20 | 소집 50 |
| 22 | 메그넘 |
| 24 | BATTLE_SLOTS 10 |
| — | 챕터 해금 = 클리어 체인 (§1.6 · CHAPTERS_10_PLAN; EA 캡 X, 장기 C) |
| 30 | (Phase 3+) 심층 시련 · 오클 완전 면세 |
2.8 전투 스탯 공식 (구현됨 — 유닛 def/hp만 해당, ATK/SPD는 §2.5 참고)
effectiveDef/hpMax = (accountBonus + nonWeaponItemStatSum + synergyBonus + positionMods)
× (1 + blessingMod)
× elementResonanceBonus
- 유닛 자체엔 기본 ATK/SPD가 없다(
BALANCE.playerBaseAtk/Spd폐기) — 무기 아이템(atk>0)만 개별 ATK/SPD를 가진다 (§2.5computeUnitWeapons). positionMods: 선택 포지션modifiers합산 (def/hp 계열에만 적용)nonWeaponItemStatSum: 그리드의 비무기 아이템 def/hp 합 — Broken 아티팩트는 0, 내구 비례 감쇠 (§4.1a)- 오클 활성화: 배치 시
activationCost차감, 미지불 시 스탯 50%만 적용
2.9 구현 단계
| Phase | 포지션 | UI |
|---|---|---|
| 1a (구현됨) | 5종 전원(오클러·마법사·기사·키메라 술사·메그넘) 고정 5인 소대, 캐릭터별 배낭 | Run 화면 멤버 탭 |
| 2 | 로스터 50 + battleSlots(Lv) 선발, 개인 스킬 채널(마법 증폭·도발 등), 키메라 오브 소환 |
Hub Roster Screen |
2.10 구 직업명 매핑 (폐기)
| 구 id (폐기) | 신 id |
|---|---|
class.warrior / Vanguard |
position.knight |
class.ranger / Striker |
assassinmagnum (체형 딜) |
class.arcanist / Weaver |
position.mage |
3. 속성(Element) 시스템
3.1 5원소 정의
| id | EN | KO | 역할 |
|---|---|---|---|
fire |
Fire | 화염 | 지속 피해, 공격 속도 |
water |
Water | 수령 | 회복, 방어, 정화 |
earth |
Earth | 대지 | 방어, 반격, 구속 |
wind |
Wind | 바람 | 속도, 회피, 연쇄 |
void |
Void | 공허 | 약점 특효, 규칙 왜곡 (희귀) |
3.2 통제 사이클 (약점)
Fire → Wind → Earth → Water → Fire (시계 방향)
Fire
↗ ↘
Water Wind
↖ ↙
Earth
| 공격 속성 | 대상 약점 | 대상 강점 |
|---|---|---|
| fire | wind | water |
| wind | earth | fire |
| earth | water | wind |
| water | fire | earth |
| void | (없음) | (없음) |
- Void 는 사이클 밖. 모든 속성에 약점 판정 없음, 대신
neutral대상에 1.15× (고정). - Void 몬스터는 모든 비-void 공격에 0.85× (완전 면역 아님).
3.3 저항 4단계
| 단계 | id | 피해 배율 | 약점 라이더 |
|---|---|---|---|
| Weak | weak |
1.30× | 해당 속성 디버프 1스택 |
| Neutral | neutral |
1.00× | 없음 |
| Resist | resist |
0.70× | 없음 |
| Immune | immune |
0.00× | 없음 (보스 페이즈 전용, 남용 금지) |
3.4 약점 라이더 (Weak 시 부여)
| 속성 | 디버프 id | 효과 | 지속 |
|---|---|---|---|
| fire | burn |
틱당 max(1, ATK×0.08) 피해 |
3틱 |
| water | chill |
SPD −30% | 4틱 |
| earth | root |
다음 공격 스킵 확률 25% | 2틱 |
| wind | expose |
DEF −25% | 3틱 |
| void | fracture |
받는 피해 +10% (중첩 3) | 5틱 |
참고: Persona류 "약점 = 데미지 + 전술 디버프" 패턴 (Marco D'Antino JRPG 설계 사례).
3.5 상성 계산 (결정론)
// shared/src/combat/element.ts
function elementMultiplier(
attackElement: Element,
defenderProfile: ElementProfile, // weak/resist per element
): { mult: number; applyRider: StatusId | null }
전투 로그에 element, mult, riderApplied 필드 추가 → 리플레이·디버그 가능.
3.6 층·바이옴과 속성
시련 UI는 로컬 1–10. 스케일·풀은
globalFloor(§1.6).
Ch.IV–X 전체 표: CHAPTERS_10_PLAN §2.
| 챕터 | 로컬 | 글로벌 | 바이옴 | 몬스터 주속성 | 상점 가중치 |
|---|---|---|---|---|---|
| I | 1–5 | 1–5 | Ember Caverns | fire | fire 40%, earth 30% |
| I | 6–10 | 6–10 | Gale Cliffs | wind | wind 40%, fire 25% |
| II | 1–5 | 11–15 | Moss Depths | earth | earth 40%, water 25% |
| II | 6–10 | 16–20 | Tide Hollows | water | water 40%, wind 25% |
| III | 1–5 | 21–25 | Rift Gallery | void | void 20%, 균등 |
| III | 6–10 | 26–30 | Ash Spire (구 Summit) | fire+void | 균등 + 티어↑ |
| IV–X | — | 31–100 | 기획 표 §2 | — | — |
4. 아이템(Item) 레벨링
4.0 오파츠 vs 아티팩트 (이원 계통)
| 필드 | Artifact | OOPArt |
|---|---|---|
origin |
'artifact' |
'oopart' |
mergeable |
true | false |
shopPool |
true | false |
maxDurability |
3~15 (티어·태그) | — (무한) |
wearPerBattle |
1 (기본) | 0 |
| 상점 | 구매·수리 | 없음 |
| 파손 시 | 스탯 0, 슬롯 점유 유지 | 영향 없음 |
Phase 1b 오파츠 목표: 8~12종 (룰 체인저 위주). 아티팩트 47종은 §4.5 유지.
머지 규칙:
- 아티팩트: §4.2 T1→T5
- 오파츠: 기본 머지 불가. Phase 2
oopart.fuse레시피 최대 3종 (동일 계열 2→1, 1회 한정)
상점 풀 분리:
shopPool(f) = { item | item.shopPool && item.origin === 'artifact' && tierUnlock(f, item) }
oopartDrop(f) = blessingPool(f) ∪ bossLoot(f) ∪ ruinEvent(f)
오파츠 그리드: 모든 오파츠는 shape로 ≥2칸 점유. proc만 주는 0칸 유물 금지 (메그넘 body 2×2 예외).
경제 루프 (시련 내):
층 보상·전투 승리로 오클 → 상점 구매/수리 → 전투 종료 시 마모(유지) → 다음 층
오파츠는 이 싱크에 끼지 않음 — 희귀하지만 마모 없음.
4.1a 아티팩트 내구도 (Durability)
무기·갑옷·장신구·소모품 = 이번 시련 안에서 오클로 보충하는 소모성 장비.
시련(1런) 안에서의 유지 — 핵심
| 동작 | |
|---|---|
| 전투 종료 | 배낭에 배치된 아티팩트 durabilityCurrent −= wearPerBattle |
| 다음 층·다음 전투 | 닳은 상태 그대로 유지 — 자동 회복 없음 |
| 상점 | 수리·재구매로만 내구 회복 |
| 시련 종료 | 배낭·내구·오클 Reserve 전부 리셋 (다음 시련은 새 출발) |
❌ 아닌 것: 전투마다 내구 풀충전 / 층 넘길 때마다 자동 수리 / 시련 간 내구 이월(메타).
예: 롱소드 5/5 → 1전투 후 4/5 → 상점 안 가면 2전투 후 3/5 … 0이면 Broken까지 그 시련 내에서 유지.
기본 규칙
| 규칙 | 내용 |
|---|---|
| 적용 대상 | origin === 'artifact' 만 |
| 오파츠 | durability 없음 — 설정상 부거·마모 없음 |
| 초기 내구 | 상점 구매·머지·드랍 시 maxDurability[tier] 풀 |
| 마모 시점 | 전투 종료 시 배치된 아티팩트 전부 −wearPerBattle |
| 추가 마모 | consumable 태그: 사용 시 −1. shield/armor: 피격 N당 −1 (Phase 1.5) |
durabilityCurrent ≤ 0 |
Broken — ATK/DEF/HP/SPD·onHit 무효. 칸 점유 유지 → 인접 시너지 끊김 |
| 제거 | 플레이어가 배낭에서 치우거나 상점 교체 — 재배치 퍼즐 유도 |
레이아웃 붕괴 (Grid-First)
Broken 아티팩트는 세금이 아니라 퍼즐 이벤트:
- L자 무기 파손 → 빈 칸 3개 + 인접
blade_wall해제 - 상점: 수리 vs 다른 shape 신규 구매 vs 판매 후 재배치
- 축복
bless.merge·bless.stash와 시너지
maxDurability (티어별 기본)
| 태그 | T1 | T2 | T3 | T4 | T5 |
|---|---|---|---|---|---|
sword / dagger |
5 | 7 | 9 | 11 | 13 |
shield / armor |
6 | 8 | 10 | 12 | 14 |
accessory |
8 | 10 | 12 | 14 | 16 |
consumable |
1 | 2 | 3 | — | — |
material |
— | — | — | — | — (머지용, 전투 미착용) |
wearPerBattle 기본값 1. Epic은 maxDurability +2.
상점 보충
| 행동 | 비용 | 효과 |
|---|---|---|
| 재구매 | buyPrice(item) |
새 인스턴스, 내구 풀 |
| 수리 | repairCost = floor(buyPrice × 0.35 × (1 - current/max)) |
내구 풀 회복 |
| 판매 | sellPrice (구매가 45%) |
Broken도 판매 가능 (급전) |
수리는 같은 defId·tier 인스턴스만. 티어업은 머지 또는 고티어 신규 구매.
머지와 내구
- 머지 결과 인스턴스: 내구 풀 (
maxDurabilityof new tier) - Broken 2개 머지: 불가 — 수리 또는 제거 후 재료만 사용
스탯 반영
itemStatContribution = broken ? 0 : baseStat // 마모 중에도 스탯 유지. Broken만 0
오클 미충전 시 underchargedStatMult(0.7) 별도 적용 — COMBAT_FORMATION.md §3.
내구 50%일 때 스탯 ≈ 70%. 완파 시 0. 오파츠는 항상 100%.
UI
- 아이템 툴팁:
Durability 4/9 - Broken: 회색 오버레이 +
ui.itemBroken - 상점:
Repair (3 ○)/Replace (8 ○)
4.1b 활성화 비용 · 인접 공명 (Grid-First)
로어: 오클 투입 = 유물 각인 가동. 이웃 유물과 태그가 맞으면 오클 흐름이 공명해 비용이 줄어든다.
활성화 (activationCost)
| 규칙 | 내용 |
|---|---|
| 전투 시작 | 배치된 각 아이템 activationCost[tier] 만큼 ochlReserve에서 일괄 차감 |
| 부족 시 | 비용 높은 순으로 활성화; 미활성 아이템은 스탯·proc 0 (칸은 점유) |
| 오파츠 | 티어 1 기준 activationCost 2~4 (아티팩트보다 높음) — 자리 싸움 |
인접 할인 (adjacency)
effectiveCost(item) = max(0, baseCost - adjacencyDiscount(item))
adjacencyDiscount = min(2, count of orthogonal neighbors where:
neighbor.tag ∩ item.synergyTags ≠ ∅
OR synergy.{id} unlocked and pair matches)
position.mage:staff/spell이웃은 추가 −1 (§2.2)- Phase 1b:
blade_wall,arcane_focus등 §4.4 시너지와 연동
상점 = 배치 페이즈
| 필드 | 값 |
|---|---|
stashCells |
4 (미배치 아이템 임시 보관) |
| 구매 후 | 즉시 배낭 배치 UI. 스태시 초과 시 판매·재배치 강제 |
| 머지 | Phase 1b: 인벤 목록 머지. Phase 1c: 배낭 인접 머지. 오브: §4.1c |
4.1c 키메라 오브 (chimera_orb)
로어·UX: DESIGN.md §키메라 오브
키메라 술사가 배낭의 오브를 두고 전투 시 소환. 별도 펜·보조 그리드 없음.
아이템 규칙
| 필드 | 값 |
|---|---|
tags |
chimera_orb |
compatiblePositions |
['chimera_sage'] |
shopPool |
false (완성 오브). 구체·촉매는 §4.1d |
mergeable |
true — 융합(Fuse) 전용 (동일 defId) |
maxDurability |
없음 (전투 마모 없음) |
wearPerBattle |
0 |
등급 ↔ shape 크기
rarity |
shape 칸 수 |
소환 배율 | activationCost (T1) |
|---|---|---|---|
| common | 2 | ×1.0 | 2 ○ |
| uncommon | 3 | ×1.4 | 3 ○ |
| rare | 4 | ×1.9 | 4 ○ |
| epic | 5~6 | ×2.6 | 5~6 ○ |
orbPower = floor(baseChimera × rarityMult[r] × cellCount^0.35)
큰 오브 = 강한 소환 + 많은 칸 + 높은 activationCost. 소대에 술사 없으면 소환 0.
전투
- 전투 시작: 배치된 각 오브 → 키메라 1체 스폰 +
activationCost차감 - 소환수: 독립 HP·ATK·속성. 오토배틀 유닛
- 전투 종료: 오브 내구도 변화 없음
획득
| 경로 | 내용 |
|---|---|
| 상점 | 기본 소환 오브 · 아티팩트 (소재 제외) |
| 키메라 처치 | 종당 상징 소재 3 · ★1–3 확률 → 보관함 (아이콘 ★공용) |
| 클리어 / 중도 포기 / 전멸 | 보관함 → 허브 수확 (오클 0 ≠ 패배) |
| 시 봉인 | 술사 보유 시 해금 · 실패 시 소재 소각 |
Phase 2: 오브 def 12~16종. shape는 등급 테이블 준수. 상세 CHIMERA_DESIGN.md.
4.1d 키메라 제작 (Poem Seal · Fuse)
마스터: CHIMERA_DESIGN.md. 포획 없음.
코어 = 5×5 소재 + 시(poem). 도감 시는 시글 해금 필수(동일 문구라도 미해금이면 Canon 아님).
자작 시 = 예술·소재 연관 AI 점수 → 스탯 가점. 특성 ≤3. 아트 = 지연 큐(즉시 생성 금지).
재료·상점
| 태그 | 출처 | 상점 |
|---|---|---|
chimera_material |
몬스터당 상징 3종 · ★1–3 확률 드랍 · 아이콘 1장/소재 · 보관함→수확 | X |
chimera_orb basic |
상점 · Poem Seal | O (T1) |
chimera_orb rare+ |
Poem Seal | X |
Poem Seal 요지
| 그리드 | 5×5, 중앙 필수 — 이미지 베이스 참조 |
| Canon | unlockedPoems + 정규화 일치 + 소재 게이트 |
| Free | AI ArtScore + MaterialRelevance → 스탯 가점 |
| Skills | ≤3 |
| Art | pending → Reveal → Nano Banana 2 / selfhost |
Fuse (보조)
동일 오브 ×2 → 티어↑. Evolve는 시 봉인으로 흡수(중복 최소화).
UI
- 허브 합성 결계: 5×5 · Seal · Reveal Form
- 도감: 시 시글 구매
- 상점: 기본 소환 · 아티팩트 풀 확대
4.1 희귀도 (Rarity)
| id | EN | 상점 가중치 | 최대 티어 | 가격 배수 |
|---|---|---|---|---|
common |
Common | 55% | 3 | ×1.0 |
uncommon |
Uncommon | 28% | 4 | ×1.4 |
rare |
Rare | 12% | 5 | ×2.0 |
epic |
Epic | 5% | 5 | ×3.0 |
4.2 티어 스케일 (머지)
stat(tier) = floor(baseStat × 1.08^(tier - 1))
price(tier, rarity) = floor(basePrice × rarityMult × tier^1.6)
| 티어 | 의미 | 머지 규칙 |
|---|---|---|
| T1 | 기본 | 상점 구매 |
| T2 | 강화 | 동일 defId T1×2 인접 머지 |
| T3 | 정예 | T2×2 또는 레시피 |
| T4 | 영웅 | T3×2 + 재료 태그 material |
| T5 | 전설 | T4×2 + 층 15+ 전용 레시피 |
4.3 아이템 스키마 확장 (ItemDef)
type ItemDef = {
id: string;
nameKey: string;
descKey: string;
origin: 'artifact' | 'oopart';
originSubtype?: 'magic' | 'science' | 'hybrid' | 'body';
mergeable: boolean;
shopPool: boolean;
shape: Shape;
rarity: Rarity;
maxTier: number;
tags: ItemTag[];
compatiblePositions?: PositionId[]; // 소대 역할. chimera_orb → ['chimera_sage']
element: Element | 'neutral';
activationCost: number[];
maxDurability: number[]; // artifact only; oopart는 빈 배열
wearPerBattle: number; // artifact 기본 1, oopart 0
atk: number[];
def: number[];
hp: number[];
spd: number[];
onHit?: CombatEffect[];
onTick?: CombatEffect[];
adjacency?: AdjacencyRule[];
};
런타임 (PlacedItem):
type PlacedItem = {
instanceId: string;
defId: string;
tier: number;
rotation: Rotation;
cells: Cell[];
durabilityCurrent?: number; // artifact
broken?: boolean;
};
4.4 태그 시너지 (런 내 레벨링)
| 시너지 id | 조건 | 보너스 | 최대 |
|---|---|---|---|
blade_wall |
sword≥2, shield≥1 | ATK +4 | 1회 |
arcane_focus |
accessory≥2, 동일 element | 해당 속성 피해 +15% | 1회 |
fortress |
armor≥2 | DEF +6, HP +20 | 1회 |
swift_steel |
sword≥2, SPD 합 ≥4 | 첫 공격 틱 −2 | 1회 |
merchants_friend |
consumable≥1 | 다음 상점 1슬롯 할인 50% | 1회 |
시너지는 런 중 해금 목록에 추가되며 UI에 배지 표시.
4.5 콘텐츠 규모 (Phase 1 목표)
| 카테고리 | origin | 수량 |
|---|---|---|
| 무기 (sword) | artifact | 12 |
| 방어 (shield/armor) | artifact | 10 |
| 악세서리 | artifact | 8 |
| 소모품 | artifact | 6 |
| 재료 (머지용) | artifact | 8 |
| 가방 확장 | artifact | 3 |
| 아티팩트 소계 | 47 | |
| 오파츠 (룰 체인저) | oopart | 8~12 |
| 오파츠 (신체/메그넘) | oopart.body | 3 |
| 합계 | ~62 (+ 레시피 15) |
5. 몬스터(Monster) 레벨링
5.1 아키타입
| id | EN | ATK | DEF | HP | SPD | AI 패턴 |
|---|---|---|---|---|---|---|
bruiser |
Bruiser | 1.2× | 0.9× | 1.3× | 0.85× | 무난 물리 |
skirmisher |
Skirmisher | 1.0× | 0.8× | 0.9× | 1.3× | 선공 |
caster |
Caster | 1.1× | 0.7× | 1.0× | 1.0× | 속성 피해 + 라이더 |
tank |
Tank | 0.8× | 1.4× | 1.5× | 0.7× | 반격 10% |
boss |
Boss | 1.3× | 1.2× | 2.5× | 1.0× | 페이즈 2 |
5.2 층 스케일 공식
기본 몬스터 스탯 (아키타입 배수 적용 전):
floorPower(f) = f^0.65 // 완만한 성장 (√~선형 사이)
tierBonus(f) = 1 + 0.04 × floor(f / 5) // 5층마다 +4% 스텝
HP (f) = round(30 × floorPower(f) × tierBonus(f))
ATK (f) = round(5 × floorPower(f) × tierBonus(f))
DEF (f) = round(2 × floorPower(f) × tierBonus(f))
SPD (f) = round(8 + f × 0.4) // 선형, 상한 22
보스 층: 챕터 내 로컬 5·10 (= 글로벌 5·10·15·20·25·30).
bossMult = 2.2 (globalFloor<15) | 2.8 (globalFloor≥15)
+ 페이즈2 @ HP 50%: ATK ×1.25, 속성 resist 1단계 상승
예시 수치 (globalFloor):
| Floor | Slime HP | Slime ATK | Goblin HP | Boss HP |
|---|---|---|---|---|
| 1 | 30 | 5 | — | — |
| 5 | 52 | 9 | 48 | 114 |
| 10 | 68 | 11 | 63 | 150 |
| 20 | 95 | 16 | 88 | 418 |
| 30 | 118 | 19 | 110 | 520 |
(실제 값은 shared/data/floors.ts + GEEvo 시뮬로 튜닝)
5.3 몬스터 테이블 스키마
type MonsterDef = {
id: string;
nameKey: string;
archetype: Archetype;
element: Element;
elementProfile: Partial<Record<Element, ResistanceTier>>;
lootTableId: string;
skills?: MonsterSkill[]; // Phase 1.5
};
5.4 전투 보상 — 마력 응결 (Condensation)
몬스터를 주워서 보상을 얻지 않는다. 처치 시 적이 흘리는 마력 잔迹(Od spill) 를, 시련 전투에 참여 중인 오클러의 응집기관이 흡수해 오클로 응고한다.
역할: 오클 수입 → 상점에서 새 조각 구매 → 배낭 재배치 (§0.1). 빌드 자체는 응결로 결정되지 않음.
| 역할 | 응결 |
|---|---|
소대 내 ochler |
talentMult 가중치 합산 |
특수 오클러 (talent.nova, ×3.5) |
로스터 1명 — 편성 시에만 가중치 적용, 필참 아님 |
mage in squad |
응결 효율 +15% 아님 — 마법사는 소비측 |
1. 적 마력 방출량 (층·난이도)
spillOd(f, tier) = baseSpill(f) × tierMult(tier)
baseSpill(f) = 3 + f + rng(0, 2) // 일반
bossSpill(f) = 8 + f × 2 // 보스 (별도 테이블)
2. 오클러별 응결 가중치
condenseWeight(ochler) =
talentMult(mageTalent)
× (allyId === SPECIAL_OCHLER_ID ? PROTAGONIST_OCHL_MULT : 1)
totalWeight = sum(condenseWeight) over ochlers in trial.battle
3. 승리 시 오클 획득
ochlGained = floor(spillOd × totalWeight / REF_WEIGHT)
// REF_WEIGHT = 1.0 (밸런스 기준점, economy.ts 데이터화)
// Phase 1a: 오클러 1명 암시 → totalWeight ≈ talentMult
4. 아이템 드랍 (물리 루팅 없음)
| 결과 | 오클 (응결) | 아이템 |
|---|---|---|
| 일반 승리 | spillOd × 가중치 합 |
없음 (아티팩트는 상점 전용) |
| 보스 승리 | bossSpill × 가중치 합 |
오파츠 1 guaranteed (유적 해방) |
| 패배 | 0 | 없음 |
UI 카피 방향: Condensed {n} Ochl from battle residue — 바닥 드랍이 아니라 코어/배낭 흡입 연출.
비채택 (확정): 엘리트·보스 처치 시 속성 오클·특수 오클 별도 지갑/화폐 없음. ochlReserve 단일 풀만. 엘리트·보스는 spillOd/bossSpill 수치 상향 + 연출(속성색 파티클)으로만 차별. 공명 버프·1칸 결정 등 2차 자원도 넣지 않음.
6. 재산(Economy) 설계
6.1 경제 그래프 (GEEvo 스타일)
flowchart LR
subgraph sources [Sources]
IdleRegen[Idle_Regen]
TrialRefund[Trial_End_Refund]
BattleCondense[Battle_Condensation]
BossBonus[Boss_Bonus]
end
subgraph pools [Pools]
Vault[Ochl_Vault_Hub]
Reserve[Ochl_Reserve_Run]
end
subgraph sinks [Sinks]
TrialEntry[Trial_Entry_Cost]
ShopBuy[Shop_Purchase]
Repair[Artifact_Repair]
Reroll[Shop_Reroll]
Activation[Item_Activation]
ExpandBag[Bag_Expand]
end
IdleRegen --> Vault
TrialRefund --> Vault
Vault --> TrialEntry
TrialEntry --> Reserve
BattleCondense --> Reserve
BossBonus --> Reserve
Reserve --> ShopBuy
Reserve --> Repair
Reserve --> Reroll
Reserve --> Activation
Reserve --> ExpandBag
Reserve -->|런 종료 100%| Vault
Phase 1a: Vault·Idle 없음 — Reserve만 (기존 gold).
6.2 오클 인플레이션 제어
| 층 f | 시작 보유(전투 후 평균) 목표 | 상점 기대 지출 |
|---|---|---|
| 1–5 | 12–18 ○ | 10–14 ○ |
| 6–15 | 18–28 ○ | 16–24 ○ |
| 16–25 | 25–40 ○ | 22–35 ○ |
| 26–30 | 35–55 ○ | 30–48 ○ |
검증 fitness (GEEvo): 시드 10,000 런 시뮬 → 층별 평균 오클이 위 밴드 ±15% 이내.
싱크: activationCost, 상점 재구매, 수리, 리롤, 시련 입장비. 아티팩트 마모가 반복 지출을 만든다.
6.3 가격 공식
buyPrice(item) = floor(rarityBase[r] × tier^1.6 × (1 + 0.03×floor))
sellPrice(item) = floor(buyPrice × 0.45) // 환금은 구매의 45%
rerollCost(f) = 1 + floor(f / 4) // 1,1,1,1,2,2,2,2,3...
6.4 메타 화폐
6.4a 포지 마크 (Sigils)
- 획득: 시련 플레이만 — 런 종료
floor × 1(승리 ×2), 일일 첫 승+5 - 용도: 도감 슬롯, 해금, 시작 축복 1회 선택 (스탯 아님), 마크 전용 치장
- 금지: ATK/HP/DEF, 오클, 오파츠, 전투력 로스터
6.4b 골드 (metaGold)
로어: 제국·아카데미가 지급하는 표준 금화. 시련 오클과 무관.
획득 (확정 — 이 경로만):
| 경로 | 예시 |
|---|---|
| 출석 | 일일 로그인, 7일 연속 |
| 퀘스트 | 일일/주간/업적 (quest.daily.*) |
| 이벤트 | 시즌·협력·층 챌린지 |
| 쿠폰 | 프로모 코드 1회 지급 |
❌ 시련 ochlReserve 환전 · ❌ 뽑기 · ❌ IAP 직접 (IAP는 premium 별도 Phase 3+)
소비 — 골드 상점 (goldShop):
| 카테고리 | cosmeticOnly |
밸런스 |
|---|---|---|
| 캐릭터 스킨 | ✅ | 영향 없음 |
| 배낭·UI 치장 | ✅ | 없음 |
| 전투 연출 (VFX/SFX) | ✅ | 없음 |
| 특수 아티팩트 | ✅ 스킨만 | 기본 defId와 동일 스탯 |
type CosmeticArtifactOffer = {
skinId: string;
baseDefId: string; // 기존 아티팩트 id — 스탯은 baseDefId에서만
priceGold: number;
cosmeticOnly: true; // 필수
};
스키마 가드: goldShop 아이템에 atk/def 필드 금지. CI에서 검증.
6.4c 화폐 격리
ochlReserve ──X──► metaGold
metaGold ──X──► ochlReserve
Sigils ──X──► ochlReserve
- 골드로 시련 입장·소환진 불가 → Grid-First·GEEvo 밸런스 유지.
6.4d 퀘스트 · 골드 지급 (quests.ts)
골드는 이 표의 경로(+ 출석·쿠폰·이벤트)로만 들어온다. 시련 보상 아님.
출석 (Daily Login)
| 항목 | 보상 |
|---|---|
| 일일 접속 | +10 metaGold |
| 7일 연속 | 추가 +40 (주간 보너스, 1회) |
| 30일 누적 | 치장 1종 또는 +200 (마일스톤, attendance.milestone) |
일일 퀘스트 — 3개 (매일 00:00 UTC 리셋)
슬롯 3개 고정. 1개 무료 리롤/일 (quest.reroll).
| id 패턴 | 예시 | 목표 | 골드 |
|---|---|---|---|
quest.daily.trial |
Complete 1 trial | 시련 1회 종료 (승패 무관) | 15 |
quest.daily.floor |
Reach Stratum 5 | 단일 시련 최고 층 ≥5 | 20 |
quest.daily.shop |
Buy 3 artifacts | 소환진 구매 3회 | 15 |
quest.daily.merge |
Synthesize once | 머지 1회 | 15 |
quest.daily.condense |
Condense 20 Ochl | 응결 누적 20 (시련 합) | 15 |
quest.daily.squad |
Deploy 4+ units | 4슬롯 이상으로 시련 시작 | 10 |
일일 풀: 위 6종 중 랜덤 3종 (중복 없음).
일일 합계 목표: 약 40~50 metaGold (적극 플레이 기준).
주간 퀘스트 — 3개 (월요일 00:00 UTC 리셋)
| id | 예시 | 목표 | 골드 |
|---|---|---|---|
quest.weekly.trials |
Academy diligence | 시련 7회 종료 | 80 |
quest.weekly.floor |
Stratum climber | 단일 시련 로컬 층 8 도달 1회 | 100 |
quest.weekly.chimera |
Seal a chimera | 시 봉인 1회 (Phase 2) | 120 |
quest.weekly.goldcap |
Complete all dailies | 일일 3개 5일 완료 | 150 |
주간 풀: 4종 중 고정 3종 (시즌별 데이터 교체 가능).
업적 (1회성)
| id | 골드 | 비고 |
|---|---|---|
quest.achieve.firstTrial |
50 | 첫 시련 |
quest.achieve.floor10 |
100 | 최고 층 10 |
quest.achieve.chapter1 |
100 | 챕터 I 클리어 |
quest.achieve.chapter3 |
300 | 챕터 III 클리어 |
quest.achieve.codex10 |
80 | 도감 10종 |
이벤트 · 쿠폰
| 경로 | 규칙 |
|---|---|
event.* |
기간 한정 퀘스트 체인, 보상 metaGold 또는 상점 한정 스킨 |
coupon.* |
1회 코드 → metaGold 또는 특정 skinId (서버 검증) |
type QuestDef = {
id: string;
nameKey: string;
descKey: string;
period: 'daily' | 'weekly' | 'achievement' | 'event';
goal: QuestGoal;
rewardGold: number;
rewardSkinId?: string; // cosmetic only
};
Phase: 출석+일일 3 → 2.5. 주간·업적 → 2.5~3. 이벤트·쿠폰 → 3.
6.4e 골드 상점 · 로테이션 (goldShop.ts)
확정 가격·확정 목록. 뽑기 없음.
cosmeticOnly: true필수.
탭 구조
| 탭 | 갱신 | 내용 |
|---|---|---|
| Featured | 주간 | 주목 스킨 1~2 (캐릭터 or 아티팩트 코스메틱) |
| Rotation | 주간 | 전투 VFX·배낭 스킨·UI 테마 4~6슬롯 |
| Permanent | 없음 | 기본 치장 (저렴, 항상 구매 가능) |
주간 로테이션 (월요일 00:00 UTC)
weekIndex = floor(unixWeek / 1) % rotationPool.length
featured[week] = rotationPool.featured[weekIndex] // 1종
rotation[week] = rotationPool.items[weekIndex] // 4~6종
| 슬롯 | 카테고리 | 가격대 (metaGold) |
|---|---|---|
| Featured ×1 | 캐릭터 스킨 | 400~600 |
| Featured ×1 (격주) | 아티팩트 코스메틱 스킨 | 300~500 |
| Rotation | 전투 VFX (응결·소환·크리) | 150~250 |
| Rotation | 배낭 격자 스킨 | 200~350 |
| Rotation | UI 테마 / 타이틀 프레임 | 100~200 |
| Permanent | 기본 프레임·단색 배낭 | 50~100 |
재출시: 동일 스킨 최소 8주 간격 (minWeeksBeforeReturn).
스키마
type GoldShopOffer = {
id: string;
nameKey: string;
kind: 'character_skin' | 'artifact_skin' | 'satchel_skin' | 'battle_vfx' | 'ui_theme' | 'title_frame';
priceGold: number;
cosmeticOnly: true;
skinId?: string;
baseDefId?: string; // artifact_skin only
rotationWeek?: number; // undefined = permanent
featured?: boolean;
};
경제 목표 (F2P)
| 플레이 패턴 | 주간 metaGold (대략) |
|---|---|
| 출석만 | ~70 |
| 출석 + 일일 3 전부 | ~70 + 7×45 ≈ 385 |
| + 주간 3 전부 | + 330 ≈ 715/주 |
| Featured 스킨 | 2~3주 모으면 1종 구매 가능 |
→ 무과금으로도 주간 스킨 1종은 2~4주에 도달 (Featured 가격 튜닝).
UI
- 허브 Gold Shop (
ui.goldShop) — 시련 중 접근 불가 - Featured 카운트다운:
Resets in {d}d {h}h - 이미 보유
skinId→ 구매 불가 (중복 방지)
Phase 2.5 구현. 시련 상점(Synth Shop)과 UI·데이터 완전 분리.
6.5 상점 풀 가중치
P(item | floor f) ∝ rarityWeight × biomeElementWeight × tierUnlock(f)
tierUnlock(f): T4는 f≥8, T5는 f≥15 에만 풀 등장
7. In-Run 축복(Floor Blessing)
층 클리어 시 3택1. 풀 가중치: 그리드형 60% · 스탯/오클형 40% (§0.1).
7.1 그리드형 (우선)
| id | 효과 |
|---|---|
bless.bag_row |
가방 +1행 (영구, 런 내) |
bless.stash |
stashCells +2 |
bless.merge |
무료 머지 1회 |
bless.rotate |
다음 상점 방문 전 무료 회전 1회 (배치 중) |
bless.shrink |
다음 구매 아티팩트 1개 shape −1칸 (최소 2칸) |
bless.slot |
상점 다음 방문 시 +1 슬롯 |
7.2 보조형
| id | 효과 |
|---|---|
bless.gold |
오클 +8 |
bless.heal |
HP 25% 회복 |
bless.sharpen |
ATK +3 (런 종료까지) |
bless.harden |
DEF +2 (런 종료까지) |
보스 층 후 희귀 축복 풀: 오파츠 1개 (≥2칸 shape) · 가방 +1행 · 무료 머지 2회.
8. 다국어(i18n)
8.1 지원 로케일 (Phase 1)
| 코드 | 언어 | 우선순위 |
|---|---|---|
en |
English | 소스 (기본) |
ko |
한국어 | P0 |
ja |
日本語 | P0 |
zh-Hans |
简体中文 | P1 |
zh-Hant |
繁體中文 | P1 |
es |
Español | P2 |
6개 로케일. Phase 2에서 de, fr 검토.
8.2 키 구조
item.{id}.name
item.{id}.desc
position.{id}.name
position.{id}.desc
oopart.{id}.name
oopart.{id}.desc
monster.{id}.name
element.{id}.name
synergy.{id}.name
synergy.{id}.desc
blessing.{id}.name
blessing.{id}.desc
ui.shop.reroll
ui.run.floor
...
- 코드 식별자·id는 영어, 표시 문자열만
t(key) shared/data/의nameKey/descKey만 저장, 번역은client/src/i18n/locales/{locale}.ts- 숫자·단위는
Intl.NumberFormat/formatGold(n)
8.3 파일 배치
client/src/i18n/
index.ts # createI18n, locale detect (navigator → en fallback)
locales/
en.ts # 소스 — 신규 키는 여기만 수동 추가
ko.ts
ja.ts
zh-Hans.ts
zh-Hant.ts
es.ts
초기엔 en + ko 만 채우고, 나머지는 en 폴백 → 점진 번역.
8.4 번역 범위 (Phase 1)
| 카테고리 | 키 수(추정) |
|---|---|
| UI 공통 | ~40 |
| 아이템 47종 ×2 | ~94 |
| 몬스터 15종 | ~15 |
| 직업·포지션·속성·시너지 | ~60 |
| 합계 | ~200 키 |
9. 데이터 파일 맵 (구현 시)
shared/data/
elements.ts
hub.ts # PARTY_MAX, regen, vaultCap, talent tables
companions.ts # 오클러 동료 풀 (Phase 2.5)
positions.ts
items/
ooparts.ts
monsters.ts
floors.ts
economy.ts
quests.ts # 일일/주간/업적 → metaGold
goldShop.ts # metaGold 로테이션 상점 (Phase 2.5)
attendance.ts # 출석 보상 (Phase 2.5)
synergies.ts
blessings.ts
chimeraRecipes.ts # Craft/Evolve 레시피 (Phase 2)
chapters.ts # TrialChapter 1-3, globalFloor
commanderLevels.ts # 구 protagonistLevels / accountLevels
shared/src/
merge/chimeraEvolve.ts # Craft/Fuse/Evolve (Phase 2)
combat/element.ts
combat/squadChannel.ts # §2.5 Squad Channel 시뮬
hub/idleRegen.ts
hub/party.ts
economy/simulate.ts
roster/applyPosition.ts
client/src/i18n/...
10. 밸런스 검증 파이프라인
- 단위 테스트: 속성 배율, 티어 스케일, 머지,
replayActions결정론 - 시뮬 테스트:
simulateRuns({ seeds: 10_000, class, targetFloor })- 챕터별 생존률 목표: 로컬 F5 85%, F10 클리어 55% (챕터 I 기준)
- Grid fitness: 동일 시드·층·오클에서 배치 3종 permutation 승률 분산 ≥ threshold
- 경제 fitness: 층별 평균 오클 밴드 (§6.2)
- CI: PR 시 시뮬 1,000 시드 스모크, main은 10,000
11. 구현 우선순위 (Phase 1b)
| 순서 | 작업 | 의존 |
|---|---|---|
| 1 | elements.ts + combat/element.ts |
combat 시뮬 |
| 2 | positions.ts + applyPosition.ts |
run 시작 |
| 3 | 아이템 origin·activationCost·durability 스키마 |
경제 |
| 3b | 전투 후 applyWear + 상점 수리·재구매 |
run FSM·shop |
| 3c | activationCost + 인접 할인 + stashCells (§4.1b) |
shop UI |
| 4 | 아티팩트 47종 + nameKey |
i18n |
| 5 | 오파츠 8종 (≥2칸 shape) + 상점 풀 분리 | shop |
| 6 | Roster Screen UI | client |
| 7 | monsters.ts + 층 스케일 + 전투 프리뷰(속성) |
floors |
| 8 | economy.ts + 응결 + 오클 밴드 검증 |
shop |
| 9 | 축복 3택1 (그리드형 우선) + 오파츠 드랍 | run FSM |
| 10 | GEEvo 시뮬 + 그리드 permutation fitness | CI |
| 11 | Hub + Roster 50 + Idle Vault + 동료 | Phase 2 |
Phase 2.5 (메타 · 치장)
| 순서 | 작업 | 스펙 |
|---|---|---|
| 12 | attendance.ts + 일일 출석 UI |
§6.4d |
| 13 | quests.ts (일일 3 + 리롤 1) |
§6.4d |
| 14 | goldShop.ts 주간 Featured/Rotation |
§6.4e |
| 15 | metaGold 지갑 + 보유 스킨 저장 |
§6.4b |
12. 현재 MVP와의 차이
| 항목 | 현재 (Phase 0) | 본 설계 (Phase 1b) |
|---|---|---|
| 속성 | 없음 | 5원소 + 약점 라이더 |
| 편성 | 없음 | 소집 ~50 + 시련 소대 4→10 |
| 시련 길이 | 무한 층 | 챕터당 로컬 10층 (글로벌 30 = 3챕터) |
| 오클 | 런 내만 (gold) |
Vault 유휴 + 입장비 + ochlReserve |
| 지휘관 | Lv1 스냅샷만 | 공적 XP·세금 감면·Lv UI (LORE) |
| 전투 | 1v1 단순 | Squad Channel (§2.5) |
| 아이템 계통 | 단일 12종 | artifact / oopart 이원 |
| 오클 활성화 | 없음 | activationCost + 인접 할인 + boundMemberId |
| 상점 UX | 구매만 | 구매→배치·stashCells 4 |
| 코어 루프 | Place 약함 | Grid-First (§0.1) |
| 아티팩트 내구 | 없음 | 전투 마모 + 상점 보충 루프 |
| 층 스케일 | 선형 placeholder | globalFloor^0.65 + tier 스텝 |
| 아이템 | 12종, T3 | artifact 47 + oopart 8~12 |
| 경제 | 고정 가격 | GEEvo 오클 밴드 |
| 메타 | 없음 | Sigils + metaGold (§6.4) |
| i18n | 6로케일 | 키 기반 + position/oopart |