규칙 집합 시트

이 페이지에서는 규칙 집합의 캐릭터 시트를 설계합니다. 능력치, 기술, 필드와 목록, 실시간 상태, 부상 트랙, 페널티, 휴식과 Game Master 텍스트, 그리고 파티 시트와 진행 시계를 다룹니다. 규칙 집합 작성자를 위한 페이지입니다. 시작하기 전에 Game Mode 규칙 집합 작성하기를 읽으세요.

시트

숫자를 읽는 것은 값 참조로 지정합니다. 정확히 하나의 키를 가진 객체이며 키는 const, field, derived, abilityScore, abilityMod, abilityModFromField, skillMod, saveMod, listSum, livePool, liveTrack, itemStat입니다. 예를 들어 최대값이 파생 값인 풀은 "max": { "derived": "grit_max" }입니다.

훈련하지 않은 판정. 캐릭터가 훈련하지 않은(단계가 첫 단계인) 기술이나 내성은 규칙 집합이 달리 정하지 않으면 평소처럼 굴립니다. 기술이나 내성, 또는 그것이 속한 구역에 untrained를 두어 정하며 기술이나 내성 자체의 규칙이 우선합니다.

"sections": [{ "id": "labour", "label": "Labour", "untrained": { "by": -1 } }],
"skills": [
  { "id": "dig", "label": "Dig", "ability": "sinew", "section": "labour", "untrained": "refuse" },
  { "id": "listen", "label": "Listen", "ability": "nerve", "untrained": "harder" }
]

능력치, 기술, 내성의 구역 지정과 모든 위치의 untrained는 패키지 규칙 집합에서 Capability API 1.41입니다.

기술이나 내성은 cap을 가질 수 있습니다. 그 판정이 도달할 수 있는 최댓값을 정하는 값 참조로, 넘어설 수 없는 평점이나 판정을 억누르는 트랙입니다. Gravewatch는 Soothe를 파수꾼에게 남은 Resolve로 제한합니다("cap": { "livePool": "resolve" }). 시트가 표시하고 모든 판정이 굴리는 숫자는 제한된 숫자이며, with= 교체는 제한 전 숫자로 계산한 뒤 다시 제한합니다. 상한은 기술이나 내성 수정치를 읽을 수 없으며, 상한이 읽는 파생 값과 그보다 앞에 선언된 파생 값도 마찬가지입니다. 따라서 시트는 여전히 위에서 아래로 한 번에 계산됩니다. Capability API 1.39.

hideWhen은 다른 필드의 값에 따라 필드, 파생 값, 목록, 풀, 일반 트랙을 숨기며 방식은 세 가지 중 정확히 하나입니다. 값 하나와 같을 때(equals), 값 하나와 다를 때(notEquals, 필드가 다른 값을 가질 때마다 숨기며 "이런 캐릭터에게만"을 표현하는 방법입니다), 값 목록에 있을 때(in)입니다. 지정한 모든 값은 필드가 가질 수 있는 값이어야 하며 그렇지 않으면 규칙이 일치할 수 없습니다. 값은 하나씩 검사하며, notEquals와 in에서는 숫자 필드의 범위와 텍스트 필드의 길이도 포함합니다. 규칙은 시트 편집기가 표시하는 값을 읽습니다. 설정하지 않은 필드는 빈 시트의 시작 값이고, 규칙 집합이 더 이상 제공하지 않는 열거형 값은 필드의 기본값입니다. 5e 파일은 equals로 주문을 쓰지 않는 캐릭터에게 주문 슬롯을 숨깁니다. Gravewatch는 "hideWhen": { "field": "watch", "notEquals": "night" }로 야간 경계를 서지 않는 모든 파수꾼의 시트에서 등불 기름을 숨깁니다. 레이어는 이 규칙들이 비교하는 값을 제외할 수 없습니다. 부상 트랙은 시트 표시와 관계없이 굴림과 전투가 읽으므로 숨길 수 없습니다. notEquals와 in은 Capability API 1.39입니다.

일반 트랙의 max는 숫자 대신 값 참조일 수 있으므로 캐릭터의 평점이 트랙 길이를 정할 수 있습니다("max": { "field": "willpower_rating" }). min과 default는 숫자로 유지합니다. 이름 붙은 단계가 있는 부상 트랙의 max는 단계 수와 같고, 번호 칸으로 된 트랙은 자체 max만큼 깁니다(아래 번호 칸 참고). alwaysShow: true는 매 턴 중요한 평점을 위해 트랙이 기본값이어도 Game Master의 시트 블록에 출력합니다. 없으면 기본값인 트랙은 생략합니다. 0인 죽음 내성 세 개는 아무 정보도 주지 않기 때문입니다. 이 세 가지는 패키지 규칙 집합에서 Capability API 1.37입니다.

실시간 상태: 형태, 자세, 불빛

열거형 필드는 캐릭터를 만들 때 고른 뒤 그대로이고, 상태 이상은 켜거나 끄는 것뿐입니다. 실시간 상태는 플레이 중 바뀌는 닫힌 집합 중 하나의 값입니다. 변신하는 캐릭터의 형태, 전투 자세, 등불의 밝기 등입니다.

"live": {
  "states": [
    {
      "id": "stance",
      "label": "Stance",
      "values": ["guarded", "steady", "reckless"],
      "valueLabels": { "guarded": "Guarded", "steady": "Steady", "reckless": "Reckless" },
      "default": "steady"
    }
  ]
}

따라오는 숫자. "op": "enumTable"인 파생 값은 열거형 필드나 실시간 상태의 각 값에 대응하는 숫자를 줍니다.

{
  "id": "stance_brawn",
  "label": "Stance on Brawn",
  "op": "enumTable",
  "from": { "liveState": "stance" },
  "table": { "guarded": -1, "reckless": 2 },
  "default": 0
}

실시간 상태, enumTable, state를 지정한 휴식 단계는 패키지 규칙 집합에서 Capability API 1.42입니다.

부상 트랙: 숫자 대신 트랙인 체력

체력을 세지 않는 시스템도 많습니다. 점점 나빠지는 칸의 열을 만들고 다칠 때 표시합니다. live.tracks 항목에 kinds와 함께 이름 붙은 levels 또는 번호가 붙은 boxes(아래 참고)를 주면 범위 숫자가 아닌 이런 형태가 됩니다.

시스템에 필요한 형태는 무엇인가요? 풀은 받은 피해량을, 트랙은 각 피해의 양과 종류를 기록합니다. 타격성, 치명성, 악화성 부상을 구분하며 악화성은 천천히 낫거나 흡수하지 못하거나 결국 죽음에 이르게 하는 등 타격 후에도 종류가 중요하면, 굴림 뒤에도 이를 보관해야 합니다. 종류를 보관하는 것은 표시뿐입니다. 점수 풀은 피해를 빼면 작은 숫자가 될 뿐 시트가 어느 점수가 어떤 종류였는지 기억하지 못합니다. 그래서 체력이 풀인 규칙 집합의 combat.damageKinds는 조용히 무시하지 않고 거부합니다. 풀에도 damageTypes를 두고 상대가 저항하거나 면역일 수 있습니다. 이는 이후 상처 종류가 아니라 타격의 얼마가 실제 들어가는지에 관한 문제이기 때문입니다.

{
  "id": "harm",
  "label": "Harm",
  "min": 0,
  "max": 4,
  "levels": [
    { "label": "Scuffed", "penalty": 0 },
    { "label": "Winded", "penalty": -1 },
    { "label": "Bleeding", "penalty": -3 },
    { "label": "Down", "penalty": -99 }
  ],
  "kinds": [
    { "id": "knock", "label": "K", "severity": 0 },
    { "id": "tear", "label": "T", "severity": 1 }
  ]
}

모호하게 이해하면 잘못된 트랙이 되므로 정확한 규칙을 설명합니다.

플레이 중 표시하기. Game Master는 [sheet: op="damage" track="harm" kind="knock" amount="1"]를 쓰고 음수 amount로 회복합니다. 칸 단위로 채우는 트랙에서는 타격이 들어갈 칸을 box="3"으로 덧붙입니다. 대신 pool=을 지정하는 기존 damage는 그대로입니다. 숫자만으로 새 표시 종류를 알 수 없어 부상 트랙에는 일반 track 명령을 거부합니다. 시스템이 기대하는 대로 플레이어도 시트에서 직접 표시하고 지울 수 있습니다.

전투도 표시할 수 있습니다. combat.health를 풀 대신 트랙에 지정하면 명중 타격이 combat.damageKinds.marks가 정한 칸 수에 해당 블록이 피해 타입을 대응시킨 종류의 표시를 남깁니다. 트랙이 가득 차면 캐릭터가 쓰러지며 죽음 규칙이 이를 읽습니다. 칸 단위로 채우는 트랙에서는 per-point 피해가 들어갈 칸을 지정하고 per-blow는 첫 칸을 겨누며, 어느 칸도 받을 수 없는 타격은 캐릭터를 쓰러뜨립니다. 이런 트랙을 쓰는 시스템에서 전투 불능이 뜻하는 바가 그것입니다. 회복은 종류와 관계없이 가장 가벼운 표시 하나를 지웁니다. 임시 점수를 둘 버퍼가 없으므로 임시 점수는 거부합니다. Engine은 트랙을 남은 단계 수로 읽으므로 전투의 다른 부분, 쓰러짐, 소생, 로그와 요약은 그대로입니다.

휴식도 부상 트랙을 회복할 수 있습니다. "to"로 트랙을 지정한 회복 단계는 초과분을 포함해 지정한 표시 수까지 줄입니다. 음수 "by"로 지정한 단계는 초과분부터 그 개수만큼 지우므로 "by": { "const": -2 }는 두 개를 지웁니다. kind도 지정한 단계는 그 종류의 표시만 지웁니다. Gravewatch의 "Catch your breath"는 { "track": "harm", "kind": "knock", "to": "min" }이며 타박은 고치고 찢긴 상처는 남깁니다. 휴식은 피해를 표시하지 않으므로 표시를 더하게 되는 단계는 아무것도 하지 않습니다. 양수 "by"도 마찬가지이며 아무 알림 없이 건너뛰므로 빼기 기호를 꼭 쓰세요.

이름 붙은 단계 대신 번호 칸

캐릭터가 강인한 만큼 트랙이 길어야 한다면 levels 대신 boxes를 주세요. 칸 수는 자체 max와 같으며, 이 값은 시트가 계산하는 값일 수 있고(실시간 상태를 읽는 값은 불가) 최대 64입니다.

{
  "id": "strain",
  "label": "Strain",
  "min": 0,
  "max": { "derived": "strain_boxes" },
  "boxes": {
    "penalty": {
      "by": "remaining",
      "table": [
        [0, -1],
        [1, 0]
      ]
    }
  },
  "kinds": [{ "id": "strain", "label": "S", "severity": 0 }],
  "fill": "indexed",
  "onFull": "refuse"
}

칸 지정 채우기와 거부하는 트랙

목록이 더하는 단계

이름 붙은 단계가 있는 트랙에 "extra": { "list": "scars", "countColumn": "levels", "penaltyColumn": "penalty" }를 주면 시트의 목록이 캐릭터마다 트랙을 늘릴 수 있습니다. 각 행은 순서대로 자기 개수만큼의 단계(최대 16)를 자기 페널티로 더하며, 페널티가 그와 같거나 더 나은 마지막 단계 뒤에 놓입니다. 페널티가 같으면 그 단계 이름을, 다르면 페널티를 이름으로 씁니다. Gravewatch의 흉터가 이렇게 작동합니다. 시트가 숨긴 목록은 아무것도 더하지 않으며, 단계에 표시가 있는 상태에서 행을 삭제하면 더 이상 들어가지 않는 표시는 초과분으로 보존합니다. 시트를 편집한다고 피해가 없어지지는 않습니다.

boxes, fill, onFull, extra, 휴식 단계의 kind는 패키지 규칙 집합에서 Capability API 1.40입니다.

굴림 페널티

resolution.penaltyFrom은 이 규칙 집합의 모든 판정에 페널티를 적용할 부상 트랙을 지정합니다. 추정하지 않고 선언하므로 생략한 규칙 집합은 부상 트랙 도입 전과 같은 방식으로 굴립니다.

페널티의 작용은 시트 숫자와 마찬가지로 판정 종류가 정합니다.

지정한 트랙은 부상 트랙이어야 합니다. 일반 트랙에는 적용할 페널티가 없어 가져올 때 거부합니다. 결과는 적용 페널티를 알려 주사위가 줄어든 이유를 보여 주며 Game Master의 시트 블록도 단계와 비용을 표시합니다.

시트의 수정치

시트의 일부 숫자는 관련된 모든 굴림에 따라붙습니다. 무거운 짐은 모든 등반에, 방어구 페널티는 모든 은신에, 축복은 모든 것에 붙습니다. resolution.adjust가 이를 선언하며 두 종류 모두에서 쓸 수 있습니다.

"adjust": [{ "value": { "derived": "burdened" }, "abilities": ["brawn"] }]

결과는 시트가 더한 값을 알려 주므로(기록의 adjust="-2"와 주사위 카드의 한 줄) 플레이어가 굴림 결과의 이유를 알 수 있습니다. 패키지 규칙 집합에서 Capability API 1.38입니다.

휴식

휴식은 회복 단계와 지울 것의 목록입니다. 각 단계는 대상 하나(pool, poolGroup, listPools, track, state)를 지정하고 값을 설정하거나("to": "max", "to": "min", 숫자) 변경합니다("by": { "const": 1 }, "by": { "fractionOfMax": 0.5 }). 부상 트랙 단계는 회복만 할 수 있으므로 by가 음수이며 위에서 설명합니다. 실시간 상태 단계는 "default"나 그 값 중 하나로 설정만 합니다. fractionOfMax가 있는 poolGroup 단계는 그룹의 각 풀을 각자의 비율만큼 바꿉니다. "shared": true(Capability API 1.77)를 더하면 대신 그룹 전체의 최대치로 비율을 계산하고, 시트가 나열한 순서대로 그룹의 풀에 각자 부족한 만큼까지 나눠 줍니다. 주사위 종류마다 풀 하나에 담는 히트 다이스의 "캐릭터 총수의 절반"을 회복하는 5e의 긴 휴식은 { "poolGroup": "hit_dice", "by": { "fractionOfMax": 0.5, "round": "down", "min": 1 }, "shared": true }입니다.

Game Master 텍스트

전체 GM 규칙 참고 자료

선택적 최상위 gmReference는 Game Master를 위한 규칙 집합의 전체 규칙 참고 자료를 최대 16,000자까지 담습니다. 확장된 재정 규칙은 여기에 두고, 짧은 판정·자원 지시는 gm.checkGuidance와 gm.sheetGuidance에 두세요. 이 필드들과 gm.worldGuidance에는 여전히 1,500자 제한이 있으며, 레이어 지침도 기존 제한을 유지합니다.

"gmReference": "When a journey crosses hostile country, judge supplies, shelter and exposure before the next leg. A failed navigation check costs time rather than silently moving the party to its destination."

참고 자료는 안정적인 시스템 프롬프트의 Game Master rules reference 아래에 요청마다 한 번 나타납니다. 턴별 리마인더에는 복사하지 않습니다. 다른 프롬프트 안전 텍스트처럼 제어 문자, 대괄호, 매크로 중괄호({{와 }}) 없이 한 줄이어야 합니다. 평소의 대화 기록·답변 예산 조정 뒤에도 요청이 컨텍스트 제한을 넘으면, 핵심 지시를 자르기 전에 잘렸다는 표시와 함께 참고 자료를 줄입니다. 기존 프롬프트를 유지하려면 설정하지 마세요. 이를 쓰는 패키지는 매니페스트에 schemaVersion: 2와 capabilityApi: { "major": 1, "minor": 145 } 이상을 선언해야 합니다.

파티와 장면의 진행 시계(clocks)

Capability API 1.143은 선택적 최상위 clocks 객체를 추가합니다. 생략하면 시계 명령은 꺼진 상태로 남습니다. 객체는 엄격하여 다음 세 키만 받습니다.

"clocks": {
  "sizes": [4, 6, 8],
  "max": 8,
  "text": "Create clocks for looming threats and long projects. Tick them when the fiction advances."
}

sizes는 2~12 사이의 서로 다른 정수 칸 수를 1~6개 허용하며 기본값은 [4, 6, 8]입니다. max는 한 번에 유지하는 시계의 최대 수로 1~12이며 기본값은 8입니다. 선택적 text는 GM이 언제 시계를 만들고 칸을 채울지 설명하는 최대 400자의 프롬프트 안전 한 줄입니다. 빈 객체는 기본값으로 켭니다.

시계는 캐릭터가 아니라 파티와 장면에 속합니다. GM 리마인더는 매 턴 시계의 이름과 채운 정도를 나열하고 다음 명령을 가르칩니다.

이름은 큰따옴표, 대괄호, 제어 문자, 매크로 중괄호가 없는 1~100자의 한 줄입니다. 각 태그는 정확히 하나의 동작을 요청합니다. 명령은 답변 순서대로 적용하므로 한 답변에서 시계를 만들고 칸을 채울 수 있습니다. Engine은 각 태그를 result="ok" now="4/6"(또는 now="cleared")이나 result="refused" reason="..."로 다시 씁니다. 모델이 쓴 결과 속성은 버립니다. 알 수 없는 시계와 잘못된 요청은 거부하며, 답변 하나에 명령은 최대 40개까지 적용합니다.

Game Mode는 파티 상태 옆에 칸으로 나뉜 원, 이름, 채운 정도를 표시합니다. 태그는 저장된 답변에 영수증으로 남고 서술에서는 숨겨집니다. 시계는 각 게임 상태 스냅샷에 rulesetClocks로 저장되며, 데이터가 없으면 시계가 없는 것입니다. 재생성은 이전 스냅샷에서, 이어 쓰기는 현재 스냅샷에서 시작하며, 스와이프나 메시지를 선택하거나 제거하면 그 스냅샷의 나머지와 함께 시계도 복원합니다.

파티 시트: 크루, 우주선, 공유 Story Points

Capability API 1.144는 sheet 옆에 선택적 최상위 party를 추가합니다. 게임마다 공유 시트 하나를 담으며, Blades의 크루, Lasers & Feelings의 우주선, Genesys의 Story Points 등이 해당합니다.

"party": {
  "label": "Crew",
  "fields": [
    { "id": "heat", "label": "Heat", "type": "number", "min": 0, "max": 9, "default": 0 },
    { "id": "vault", "label": "Vault capacity", "type": "number", "min": 0, "max": 16, "default": 8 },
    { "id": "upgrades", "label": "Upgrades", "type": "text", "maxLength": 400 }
  ],
  "pools": [{ "id": "coin", "label": "Coin", "max": { "field": "vault" }, "start": "empty" }],
  "advancement": { "fields": ["heat", "vault", "upgrades"], "text": "Record heat after a score." },
  "text": "Coin belongs to the crew."
}

fields는 sheet.fields와 같은 필드 스키마를 쓰고, pools는 start, group, hideWhen, allowTemp를 포함해 sheet.live.pools와 같은 스키마를 씁니다. 필드나 풀이 하나 이상 필요하며 ID는 파티 시트 안에서 고유해야 합니다. 캐릭터와 파티의 ID는 겹쳐도 됩니다. 이 마이너 버전에서 파티 시트에는 구역, 목록, 능력치, 파생 값, 캐릭터 시트 마이그레이션이 없습니다. 풀의 max는 상수나 파티의 숫자 필드를 읽습니다. 캐릭터 공식은 파티 값을 읽을 수 없고, 파티 공식은 캐릭터 값을 읽을 수 없습니다. hideWhen도 파티 필드만 지정합니다.

advancement.fields는 GM이 영구히 바꿀 수 있는 number, text, longtext 필드를 지정합니다. advancement.text와 text는 각각 최대 400자의 프롬프트 안전 한 줄을 받습니다. 선택적 summary는 gm.sheetSummary를 재사용합니다. fields는 파티 필드를 고르며 derived와 lists는 비어 있어야 합니다. 요약이 없으면 보이는 파티 필드를 모두 표시합니다. 풀은 항상 나타납니다.

[sheet: sheet="party" op="restore" pool="coin" amount="3"]
[sheet: sheet="party" op="spend" pool="coin" amount="2"]
[sheet: sheet="party" op="advance" field="heat" by="2"]
[sheet: sheet="party" op="advance" field="upgrades" to="Hidden vault"]

sheet="party"는 공유 시트를 고르며 who는 생략합니다. 기존 who="party"는 여전히 모든 캐릭터에 적용되며 공유 시트는 바꾸지 않습니다. 이 마이너 버전은 파티 시트에서 spend, restore, 필드 advance를 허용합니다. 알 수 없는 시트, 지원하지 않는 동작, 부족한 풀, 선언하지 않은 성장, 잘못된 값은 거부하고 Engine의 결과로 다시 씁니다. 파티 풀은 캐릭터 풀과 같은 현재값/최대값 계산과 기본값을 따릅니다.

GM은 매 턴 캐릭터 시트 블록 옆에서 파티 라벨, 필드, 풀을 받습니다. Game Mode는 캐릭터 초상화 옆에 같은 시트 표시를 쓰는, 접을 수 있는 읽기 전용 파티 시트를 제공합니다. 영구 값은 채팅 메타데이터(gamePartySheet)에 gameCharacterCards와 나란히 한 번만 저장되며 성장 영수증을 공유합니다. 실시간 풀은 rulesetLive의 예약된 $party 항목을 쓰며, 정규화된 캐릭터 이름은 이와 겹칠 수 없습니다. 재생성은 답변 이전 상태에서 시작하며, 스와이프 선택이나 삭제는 기존 기록을 통해 영구 값과 실시간 값을 모두 복원합니다. party가 없는 규칙 집합은 기존 동작을 유지합니다.

공유 파티 생성(Capability API 1.163). 파티 시트는 lists(최대 12개이며 캐릭터 시트의 목록처럼 작성), 자체 안내형 builder, fromMembers를 가질 수 있습니다. 이는 파티의 캐릭터에서 읽는 파티 숫자 필드 최대 8개이며, 각각 { "field", "count": true }(캐릭터 수) 또는 { "field", "sum": "<character number field>" }(Totem 점처럼 캐릭터들의 값을 합한 것)입니다. 구성원 필드는 공유 시트를 읽을 때마다 그 시점의 캐릭터로 계산하므로 캐릭터가 합류하거나 떠나면 즉시 바뀝니다. 목록이 있으면 파티 summary.lists가 이를 지정할 수 있습니다.

빌더는 캐릭터의 빌더와 똑같이 작성하며(풀, 단계, 가격이 붙은 행, 소비 제안, 프로필), 파티 자체 필드와 목록을 기준으로 같은 규칙을 따릅니다. 카탈로그 단계와 행 복사 단계는 파티 목록에 공급하는 규칙 집합의 카탈로그를 읽을 수 있습니다. Game Mode에서는 어느 플레이어든 공유 시트의 Edit를 열 수 있으며, 여기서 안내형 설정을 제공하고 파티 전체를 위해 저장합니다. 각 저장은 그것을 연 시점의 리비전을 지정합니다(채팅 메타데이터의 gamePartySheetRevision이며 모든 저장과 이야기 자체의 변경이 올림). 다른 사람의 저장이 반영되기 전에 연 저장은 거부하고 더 새로운 시트를 보여 주며, 플레이어의 초안은 열린 채로 남으므로 다시 저장해 교체할지는 플레이어가 고릅니다.

"party": {
  "label": "The Crew",
  "fields": [
    { "id": "tier", "label": "Tier", "type": "number", "min": 0, "max": 4, "default": 0 },
    { "id": "size", "label": "Crew size", "type": "number", "min": 0, "max": 12, "default": 0 }
  ],
  "lists": [{ "id": "upgrades", "label": "Upgrades", "columns": [{ "id": "name", "label": "Name", "type": "text" }] }],
  "builder": { "steps": [{ "id": "upgrades", "label": "Upgrades", "kind": "rows", "list": "upgrades" }] },
  "fromMembers": [{ "field": "size", "count": true }]
}