주민과 직업
01 게임
이 문서 안에서
왕국을 굴리는 사람이 무엇으로 이루어져 있는지를 정합니다. 직업 7종, 세이브 구조, 화면 표시 규칙. 누구를 뽑느냐는 명부와 영입, 키우는 법은 성장과 레벨.
한 줄 요약 — 세이브에 남는 것은
rosterId한 줄뿐이고, 이름·얼굴·능력치는 화면을 그릴 때마다 다시 읽습니다.
1. 직업 7종
VillagerRole 문자열 유니온.
얼굴은 구운 시트 옆의 assets/sprites/characters/<id>.json이 portrait로 가리키는 칸입니다 ({ row, column, x, y, width: 48, height: 48 }). 걷는 줄 넷 중 어느 것이 앞모습인지는 그 파일만 알고 있어서 — 농부와 요리사는 6번 줄, 나머지 다섯은 2번 줄 — 문서가 정할 수 없습니다. 영입 후보 <id>-1~<id>-6도 같은 자리를 각자 적어 둡니다(명부와 영입).
| 갈래 | 직업 | 주머니 | 상세 하단 |
|---|---|---|---|
| 채집직 | 농부·나무꾼·광부·어부 | 있음 | 수량·분당 채집량 |
| 가공직 | 요리사·대장장이 | 없음 | 부엌/대장간 버튼 (제작 유일 입구) |
| 전투직 | 전사 | 없음 | 전투 진행·던전 목록 |
표시 순서(RECRUITABLE_ROLES): farmer→woodcutter→miner→fisher→cook→blacksmith→warrior.
폐기 직업: 정찰병·상인은 카탈로그에서 삭제되었습니다. 출시 전이라 되돌릴 세이브가 없으므로 마이그레이션도 없습니다 (세이브와 마이그레이션).
2. 후보가 가방에 넣는 것
villagerYields(rosterId) — 카탈로그에서 파생. 단위는 사람.
| 후보 | 산출물 | 개수 | 출처 |
|---|---|---|---|
| 채집직 골드 후보 | 작업지 자원 (체인 전부) | 체인 단계 수 | worksitesForRole |
| 채집직 인장 후보 | 전용 재료 (황금 밀·신목 원목·심해 진주) | 1 | PREMIUM_ |
| 골드 광부 | 일반 광산 7곳 광물 | 7 | ORDINARY_ |
| 인장 광부 | 미스릴 | 1 | MINES(sealOnly) |
| 요리사 | 레퍼토리 산출물 | 3·5·4·7·7·8 | CRAFT_×CRAFT_ |
| 대장장이 | 레퍼토리 산출물 | 2·3·4·4·6·6 | 같음 |
| 전사 | 전리품 재료 | 18 | LOOT_ |
인장 후보는 평범한 자원을 대체합니다(상위호환 아님). 명부와 영입 참조.
3. 작업 애니메이션
224×120 비네트. 배우 y=108, x=88, 배율 0.85. 직업 11종 전부에 있습니다(VIGNETTE_ROLES) — tests/villager-vignette.test.ts 가 그것을 지킵니다. 없는 동안 가구 장인·건축가·사냥꾼·약초꾼의 상세 카드는 다른 직업이 일하는 자리에 빈 상자를 띄웠고, 아무것도 실패하지 않아서 오래 남아 있었습니다.
| 직업 | 애니메이션 | 연장 레이어 | 배경 |
|---|---|---|---|
| 농부 | thrust | tool_hoe | bg- |
| 나무꾼 | tool_axe | tool_axe | bg- |
| 광부 | tool_axe | tool_ | bg-(광산별 8종) |
| 어부 | tool_rod | tool_rod | bg- |
| 요리사 | thrust | 없음 | bg- |
| 대장장이 | tool_ | tool_ | bg- |
| 전사 | slash_128 | weapon_ | bg-(전투 비네트가 우선) |
| 사냥꾼 | shoot | weapon_+화살 | bg- (임시) |
| 약초꾼 | thrust | 없음(맨손) | bg- |
| 건축가 | thrust | tool_ | bg- |
| 가구 장인 | tool_ | tool_ | bg- (임시) |
사냥꾼의 활은 shoot 행에만 그려져 있습니다 — 광장을 걷는 사냥꾼은 맨손이고, 초상화도 그대로입니다. 임시 배경 2장은 그려야 할 아이콘 에 목록이 있습니다.
효과음 첫 박: 주기 35% 지점. 산출물 아이콘: 실제 증가 시에만(400ms 폴링). 무엇이 "증가"인지는 직업마다 다릅니다 — 채집직은 주머니, 약초꾼은 채집망 총량, 건축가와 가구 장인은 아무것도 튀지 않습니다. 둘이 만드는 것은 건물과 가구이고, 어느 쪽도 인벤토리 한 줄이 아니라서 튈 아이콘이 없습니다.
4. 세이브 구조 (VillagerState)
| 필드 | 무엇 |
|---|---|
id | vil_ + 시각 36진수 + 난수 4자 |
name | 영입 시 지역화 이름 |
role | 7종 중 하나 |
rosterId | 명부 후보 id — 얼굴·능력치 유일 출처 |
level | 골드 레벨업 축 |
hp·maxHp | 전사만 (전투) |
status | idle/working/resting (불변) |
gatheredAt | 주머니 시계 기준 |
mineId·mineGrants | 광부 배정·개방 허가 |
siteId | 작업지 배정 (농부·나무꾼·사냥꾼·어부) |
equipment·enchant | 3슬롯 장비·각인 |
buffs | 음식 버프 (모든 지속 버프가 여기 저장) |
battle | 전사 개인 전투 진행 (던전 배정·대미지·전리품·녹다운) |
assignment·skills | 예약 (읽는 코드 없음) |
rosterId → 명부 id, 캐릭터 정의(data/characters/{id}.json), 스프라이트(assets/sprites/characters/{id}.png), i18n(villager.name.{id}).
언어 변경 시 영입 주민 이름표도 전부 바뀜(의도). rosterId가 null(v10 이하): 이름은 세이브 v.name, 얼굴 직업 원본, 능력치 BASELINE_TRAITS, 레퍼토리 전 메뉴.
5. 표시 규칙
| 함수 | 규칙 |
|---|---|
rosterName(id) | t("villager. |
villagerName(v) | rosterId → 지역화, 없으면 v. |
villagerCharacterId(v) | rosterId → 구운 캐릭터, 없으면 roleCharacterId |
applyPortrait(el, id, size) | 구운 시트 정면 프레임, 흉상 창 {x: |
초상 크기: 카드 36px, 상세·영입 48px. image-rendering: pixelated.
6. 개성 12종 (data/villager-persona.json)
후보 66명 전원이 성격 유형 하나를 가집니다. 능력치가 "무엇을 할 수 있는가"라면 개성은 "누구인가"입니다.
| id | 한국어 | 인원 |
|---|---|---|
diligent | 성실한 | 7 |
proud | 자부심 강한 | 7 |
meticulous | 깐깐한 | 7 |
gentle | 온화한 | 6 |
quiet | 말수 적은 | 6 |
dreamer | 몽상가 | 6 |
stubborn | 고집 센 | 5 |
gruff | 무뚝뚝한 | 5 |
wry | 능청스러운 | 5 |
cheerful | 명랑한 | 4 |
timid | 조심스러운 | 4 |
curious | 호기심 많은 | 4 |
한 직업의 후보 6명은 서로 다른 개성 4종 이상을 가집니다(테스트가 강제). 같은 값의 농부 둘이 같은 사람으로 읽히지 않게 하는 장치입니다.
글은 세 갈래로 나눠 씁니다.
| 열쇠 | 수 | 누구 것 | 어디에 |
|---|---|---|---|
villager. | 66 | 1인 전용 자기소개 (1인칭) | 후보 상세 팝업 |
villager. | 66 | 1인 전용 대사 | 주민 상세 말풍선(카드 열 때) |
villager. | 36 | 개성 공용 | 주민 상세 말풍선(상황별) |
villager. | 12 | 개성 이름 | 두 화면의 칩 |
상황 4종(SaySituation): greet(카드 열기 — 개인 대사로 해석) · work(말풍선 탭) · collect(수거 성공 직후) · levelup(레벨업 직후). 상황별 대사를 사람당 쓰지 않고 개성당 쓰는 이유: 66명 × 3상황 = 198줄은 나란히 읽힐 일이 없고, 플레이어가 직접 비교하는 것(후보를 눌러 여는 상세 팝업의 자기소개, 상세 첫 줄)만 1인 전용이면 충분합니다.
rosterId가 null인 주민(명부 이전 세이브)은 개성이 없습니다. 조회 함수 전부 null/""을 돌려주고 화면은 줄을 숨깁니다 — 플레이어가 직접 이름 붙인 사람에게 말을 넣지 않기 위한 규칙입니다.
7. 캐릭터 정의 (data/characters/*.json)
50개 = 직업 원본 7 + 후보 42 + steward 1. 키 6개: id, name, description, bodyType, animations, layers.
분포: female 22, male 20, teen 8. 손으로 쓴 8개(원본+steward), 생성 42개(tooling/lpc/generate-villagers.mjs).
구운 시트: pnpm lpc:bake → assets/sprites/characters/. 64×64 표준, 오버사이즈 128×128 별도 파일. 아트와 LPC 캐릭터 참조.
이어서 읽기
- 명부와 영입 — 42명 이름·가격·차단 사유
- 성장과 레벨 — 레벨업 곡선
- 채집과 주머니 — 채집직 산출량·광산
- 제작 — 가공직 레시피
- 전투 — 전사 개인 전투와 던전
- 구현 상태 — 어긋남과 미구현 항목