Compare commits

..
4 Commits
Author SHA1 Message Date
cthangover 59663653a4 Add mod documentation in seven languages 2026-10-29 09:26:07 +01:00
iisaev 4876275f81 gitignore file 2026-10-28 15:20:00 +03:00
cthangoverandClaude Opus 5.5 fd4f9e4c25 Quest action schemas with texts in seven languages
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 10:01:15 +02:00
cthangover c6262ddafe Localization in es, zh, ja, ko, vi 2026-10-23 20:54:45 +02:00
27 changed files with 797 additions and 3 deletions

No files matched your search

+1
View File
@@ -12,6 +12,7 @@ obj/
gen/ gen/
obj/ obj/
bin/ bin/
art_sources/
*.tres~ *.tres~
*.tscn~ *.tscn~
Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

+81
View File
@@ -0,0 +1,81 @@
# Quests Engine — quests, their steps and the journal
Quests Engine keeps track of the player's tasks. A quest has a name and a numbered list of steps; scenarios start it, move it to the next step, mark things with tags and finish it. The **Journal** panel shows the quests the player has taken, and the game saves their state.
It is used by Cthangover (the prologue's awakening and the old house) and by RPG Plus (the woodland quests).
## The journal
Open it with the journal icon on the toolbar. Before the player has taken any quest, it is empty:
![The Journal in RPG Plus at the start: Active and Completed tabs, "No quests" on both pages.](assets/journal-before.jpg)
In RPG Plus the elder of the village gives the first quest. Ask him where to look:
![The elder's house: the hero in front of the elder, two answers on the right — "Can a wolf put out lamps?" and "Where do I find it?".](assets/elder-choice.jpg)
After the answer the quest is in the journal:
![The Journal after the talk: "A light on the ledger" in the Active list; on the right "Entry II of V", the first step struck through and the current step "Defeat the wolf by the cave in the eastern forest. Find the amber heart."](assets/journal-after.jpg)
- **Active** lists quests in progress, **Completed** the finished ones. Quests not yet started never appear.
- The right page shows the selected quest: steps already done are struck through, the current step is marked, and later steps stay hidden, so the journal never gives the story away.
- Tags the quest has earned are shown as small gold labels under the entry.
## A quest definition
Quests are JSON files of kind `quest` in a mod's `quests/` folder. This is the quest from the pictures (from RPG Plus):
```json
{
"Kind": "quest",
"Items": [
{
"Id": "woodland_ward",
"Name": "rpg_plus/quest/ward/name",
"StatusToDescription": {
"0": "rpg_plus/quest/ward/0",
"1": "rpg_plus/quest/ward/1",
"2": "rpg_plus/quest/ward/2",
"3": "rpg_plus/quest/ward/3",
"4": "rpg_plus/quest/ward/4"
}
}
]
}
```
`Name` and every step are translation keys. The numbers are the quest's **step**: step 1 shows the text of `1` as current and `0` struck through — "Entry II of V" in the picture.
## Moving a quest from a scenario
The elder's answer in RPG Plus starts the quest and puts it on step 1:
```scenario
action quest.set_status quest_id=woodland_ward status=Progress
action quest.set_data_status quest_id=woodland_ward level=1
```
- `quest.set_status` — the quest's state: `NotStarted`, `Progress` (active) or `End` (completed).
- `quest.set_data_status` — the current step, `level` is its number.
- `quest.add_tag` / `quest.remove_tag` with `tag=…` — remember something that happened, for example which item the player took first.
- `quest.send_notification` — shows the player a notification about the quest; changing a quest does not do this by itself.
## Checking a quest
Quest checks work wherever the game takes a condition: `when`, answer conditions, scene conditions and map events.
```scenario
when "woodland_ward.DataStatus >= 2" -> :lantern
```
- `<quest>.IsActive` — the quest is in progress;
- `<quest>.Status` — `0` not started, `1` in progress, `2` completed;
- `<quest>.DataStatus` — the current step;
- `<quest>.hasTag("tag")`, `<quest>.notHasTag("tag")` — Cthangover uses these to pick which scenario of a scene plays, for example `AwakeningQuest.hasTag("book_taken")`.
## If something goes wrong
1. **The quest is not in the journal.** Its state must be `Progress` (or `End` for the Completed tab); setting only the step is not enough.
2. **The journal shows a key instead of text.** Add the step's key to the mod's `locale` files.
3. **A condition is always false.** The quest id is spelled differently from the `Id` in the quest file; the log warns about an unknown quest.
+81
View File
@@ -0,0 +1,81 @@
# Quests Engine — misiones, sus pasos y el diario
Quests Engine lleva la cuenta de las tareas del jugador. Una misión tiene un nombre y una lista de pasos numerados; los escenarios la inician, la llevan al paso siguiente, le ponen etiquetas y la completan. El panel **Diario** muestra las misiones que el jugador ha tomado, y el juego guarda su estado.
Lo usan Cthangover (el despertar del prólogo y la casa vieja) y RPG Plus (las misiones del bosque).
## El diario
Se abre con el icono del diario en la barra de herramientas. Mientras el jugador no haya tomado ninguna misión, está vacío:
![El diario de RPG Plus al empezar: pestañas Activas y Completadas, «No hay misiones» en ambas páginas.](assets/journal-before.jpg)
En RPG Plus, el anciano del pueblo da la primera misión. Pregúntale dónde buscar:
![La casa del anciano: el héroe frente al anciano, dos respuestas a la derecha — «¿Puede un lobo apagar faroles?» y «¿Dónde lo encuentro?».](assets/elder-choice.jpg)
Tras la respuesta, la misión aparece en el diario:
![El diario tras la charla: «Una luz en el libro de cuentas» en la lista de activas; a la derecha «Entrada II de V», el primer paso tachado y el paso actual «Vence al lobo de la cueva del bosque del este. Encuentra el corazón de ámbar».](assets/journal-after.jpg)
- **Activas** reúne las misiones en curso y **Completadas** las terminadas. Las misiones aún no empezadas no aparecen nunca.
- La página derecha muestra la misión seleccionada: los pasos hechos van tachados, el paso actual queda marcado y los futuros siguen ocultos, así el diario no adelanta la historia.
- Las etiquetas que la misión ha ganado se muestran como pequeñas placas doradas bajo la entrada.
## Una definición de misión
Las misiones son archivos JSON de tipo `quest` en la carpeta `quests/` de un mod. Esta es la misión de las imágenes (de RPG Plus):
```json
{
"Kind": "quest",
"Items": [
{
"Id": "woodland_ward",
"Name": "rpg_plus/quest/ward/name",
"StatusToDescription": {
"0": "rpg_plus/quest/ward/0",
"1": "rpg_plus/quest/ward/1",
"2": "rpg_plus/quest/ward/2",
"3": "rpg_plus/quest/ward/3",
"4": "rpg_plus/quest/ward/4"
}
}
]
}
```
`Name` y cada paso son claves de traducción. Los números son el **paso** de la misión: en el paso 1 se muestra el texto de `1` como actual y el de `0` tachado — «Entrada II de V» en la imagen.
## Mover una misión desde un escenario
La respuesta del anciano en RPG Plus inicia la misión y la pone en el paso 1:
```scenario
action quest.set_status quest_id=woodland_ward status=Progress
action quest.set_data_status quest_id=woodland_ward level=1
```
- `quest.set_status` — el estado de la misión: `NotStarted`, `Progress` (activa) o `End` (completada).
- `quest.set_data_status` — el paso actual; `level` es su número.
- `quest.add_tag` / `quest.remove_tag` con `tag=…` — recordar algo que ocurrió, por ejemplo qué objeto cogió primero el jugador.
- `quest.send_notification` — muestra al jugador un aviso sobre la misión; cambiar una misión no lo hace por sí solo.
## Comprobar una misión
Las comprobaciones de misiones funcionan dondequiera que el juego admita una condición: `when`, condiciones de respuesta, condiciones de escena y eventos de mapa.
```scenario
when "woodland_ward.DataStatus >= 2" -> :lantern
```
- `<quest>.IsActive` — la misión está en curso;
- `<quest>.Status` — `0` no empezada, `1` en curso, `2` completada;
- `<quest>.DataStatus` — el paso actual;
- `<quest>.hasTag("tag")`, `<quest>.notHasTag("tag")` — Cthangover las usa para elegir qué escenario de una escena se reproduce, por ejemplo `AwakeningQuest.hasTag("book_taken")`.
## Si algo falla
1. **La misión no está en el diario.** Su estado debe ser `Progress` (o `End` para la pestaña de completadas); fijar solo el paso no basta.
2. **El diario muestra una clave en vez de texto.** Añade la clave del paso a los archivos `locale` del mod.
3. **Una condición siempre es falsa.** El id de la misión está escrito distinto del `Id` del archivo de la misión; el registro avisa de una misión desconocida.
+81
View File
@@ -0,0 +1,81 @@
# Quests Engine — クエスト、そのステップ、ジャーナル
Quests Engine はプレイヤーのタスクを管理します。クエストには名前と番号付きのステップ一覧があり、シナリオがクエストを開始し、次のステップへ進め、タグを付け、完了させます。**ジャーナル**パネルにはプレイヤーが受けたクエストが表示され、その状態はゲームのセーブに保存されます。
Cthangover(プロローグの目覚めと古い家)と RPG Plus(森のクエスト)がこれを使っています。
## ジャーナル
ツールバーのジャーナル・アイコンで開きます。プレイヤーがまだクエストを一つも受けていなければ、空です。
![RPG Plus の開始時点のジャーナル: 進行中と完了のタブ、どちらのページにも「クエストはありません」。](assets/journal-before.jpg)
RPG Plus では村の長老が最初のクエストを出します。どこへ探しに行けばいいか尋ねてみましょう。
![長老の家: 長老を前にした主人公、右側に二つの選択肢「狼に灯を消せるのか?」と「どこで探せばいい?」。](assets/elder-choice.jpg)
答えると、クエストがジャーナルに現れます。
![会話後のジャーナル: 進行中の一覧に「台帳に載った灯り」。右側は「項目 II / V」で、最初のステップは打ち消し線、現在のステップは「東の森の洞窟のそばの狼を倒し、琥珀の心臓を見つけよう」。](assets/journal-after.jpg)
- **進行中**には進行中のクエスト、**完了**には終わったクエストが並びます。まだ始めていないクエストは決して表示されません。
- 右のページには選んだクエストが出ます。済んだステップには打ち消し線、現在のステップには印が付き、先のステップは隠れたまま。ジャーナルが物語を先にばらすことはありません。
- クエストが獲得したタグは、項目の下に小さな金色の札として表示されます。
## クエストの定義
クエストは、mod の `quests/` フォルダーに入る kind `quest` の JSON ファイルです。こちらは画像のクエスト(RPG Plus のもの)です。
```json
{
"Kind": "quest",
"Items": [
{
"Id": "woodland_ward",
"Name": "rpg_plus/quest/ward/name",
"StatusToDescription": {
"0": "rpg_plus/quest/ward/0",
"1": "rpg_plus/quest/ward/1",
"2": "rpg_plus/quest/ward/2",
"3": "rpg_plus/quest/ward/3",
"4": "rpg_plus/quest/ward/4"
}
}
]
}
```
`Name` と各ステップは翻訳キーです。番号がクエストの**ステップ**になります。ステップ 1 では `1` のテキストが現在のステップとして表示され、`0` には打ち消し線が付きます。画像でいう「項目 II / V」です。
## シナリオからクエストを進める
RPG Plus で長老の答えがクエストを開始し、ステップ 1 に置きます。
```scenario
action quest.set_status quest_id=woodland_ward status=Progress
action quest.set_data_status quest_id=woodland_ward level=1
```
- `quest.set_status` — クエストの状態。`NotStarted`、`Progress`(進行中)、`End`(完了)。
- `quest.set_data_status` — 現在のステップ。`level` がその番号です。
- `quest.add_tag` / `quest.remove_tag` と `tag=…` — 起こったことを記録します。たとえばプレイヤーがどのアイテムを先に取ったか。
- `quest.send_notification` — クエストについての通知をプレイヤーに表示します。クエストを変えただけでは通知は出ません。
## クエストの確認
クエストの判定は、ゲームが条件を受け付ける場所ならどこでも機能します。`when`、選択肢の条件、シーンの条件、マップイベントです。
```scenario
when "woodland_ward.DataStatus >= 2" -> :lantern
```
- `<quest>.IsActive` — クエストが進行中。
- `<quest>.Status` — `0` 未開始、`1` 進行中、`2` 完了。
- `<quest>.DataStatus` — 現在のステップ。
- `<quest>.hasTag("tag")`、`<quest>.notHasTag("tag")` — Cthangover はこれでシーンのどのシナリオを再生するか決めます。例は `AwakeningQuest.hasTag("book_taken")`。
## うまく動かないとき
1. **クエストがジャーナルに出ない。** 状態が `Progress`(完了タブに出すなら `End`)である必要があります。ステップだけ設定しても足りません。
2. **ジャーナルがテキストではなくキーを表示する。** ステップのキーを mod の `locale` ファイルに追加してください。
3. **条件が常に偽になる。** クエスト id のつづりがクエストファイルの `Id` と違います。ログには未知のクエストの警告が出ます。
+81
View File
@@ -0,0 +1,81 @@
# Quests Engine — 퀘스트, 단계, 그리고 저널
Quests Engine은 플레이어의 과제를 관리합니다. 퀘스트는 이름과 번호가 붙은 단계 목록을 가지며, 시나리오가 퀘스트를 시작하고 다음 단계로 진행하고 태그를 달고 완료합니다. **저널** 패널은 플레이어가 수락한 퀘스트를 보여 주고, 게임은 그 상태를 저장합니다.
Cthangover(프롤로그의 각성과 낡은 집)와 RPG Plus(숲의 퀘스트)가 이를 사용합니다.
## 저널
툴바의 저널 아이콘으로 엽니다. 플레이어가 아직 퀘스트를 하나도 수락하지 않았다면 비어 있습니다.
![RPG Plus 시작 시점의 저널: 진행 중과 완료 탭, 두 페이지 모두 "퀘스트가 없습니다".](assets/journal-before.jpg)
RPG Plus에서는 마을 원로가 첫 퀘스트를 줍니다. 어디를 찾아야 하는지 물어 보세요.
![원로의 집: 원로 앞에 선 주인공, 오른쪽의 두 선택지 "늑대가 등불을 끌 수 있나요?"와 "어디서 찾죠?".](assets/elder-choice.jpg)
답을 고르면 퀘스트가 저널에 나타납니다.
![대화 후의 저널: 진행 중 목록의 "장부에 오른 등불"; 오른쪽은 "항목 II / V", 첫 단계는 취소선, 현재 단계는 "동쪽 숲 동굴의 늑대를 물리치고, 호박 심장을 찾으세요".](assets/journal-after.jpg)
- **진행 중**에는 진행 중인 퀘스트가, **완료**에는 끝난 퀘스트가 들어갑니다. 아직 시작하지 않은 퀘스트는 결코 나타나지 않습니다.
- 오른쪽 페이지는 선택한 퀘스트를 보여 줍니다. 끝낸 단계에는 취소선이, 현재 단계에는 표시가 붙고, 이후 단계는 감춰져 있어 저널이 이야기를 미리 까발리지 않습니다.
- 퀘스트가 얻은 태그는 항목 아래에 작은 금색 꼬리표로 표시됩니다.
## 퀘스트 정의
퀘스트는 mod의 `quests/` 폴더에 있는 kind `quest` JSON 파일입니다. 사진 속 퀘스트(RPG Plus 것)입니다.
```json
{
"Kind": "quest",
"Items": [
{
"Id": "woodland_ward",
"Name": "rpg_plus/quest/ward/name",
"StatusToDescription": {
"0": "rpg_plus/quest/ward/0",
"1": "rpg_plus/quest/ward/1",
"2": "rpg_plus/quest/ward/2",
"3": "rpg_plus/quest/ward/3",
"4": "rpg_plus/quest/ward/4"
}
}
]
}
```
`Name`과 각 단계는 번역 키입니다. 숫자가 퀘스트의 **단계**입니다. 단계 1에서는 `1`의 텍스트가 현재 단계로 표시되고 `0`에는 취소선이 그려집니다. 사진으로 말하면 "항목 II / V"입니다.
## 시나리오에서 퀘스트 진행하기
RPG Plus에서 원로의 대답이 퀘스트를 시작하고 단계 1에 놓습니다.
```scenario
action quest.set_status quest_id=woodland_ward status=Progress
action quest.set_data_status quest_id=woodland_ward level=1
```
- `quest.set_status` — 퀘스트의 상태: `NotStarted`, `Progress`(진행 중) 또는 `End`(완료).
- `quest.set_data_status` — 현재 단계, `level`이 그 번호입니다.
- `quest.add_tag` / `quest.remove_tag`와 `tag=…` — 일어난 일을 기억합니다. 예를 들어 플레이어가 어떤 아이템을 먼저 가져갔는지.
- `quest.send_notification` — 퀘스트에 대한 알림을 플레이어에게 보여 줍니다. 퀘스트를 바꾸는 것만으로는 알림이 뜨지 않습니다.
## 퀘스트 확인하기
퀘스트 판정은 게임이 조건을 받아들이는 곳이라면 어디서든 작동합니다. `when`, 선택지 조건, 장면 조건, 맵 이벤트입니다.
```scenario
when "woodland_ward.DataStatus >= 2" -> :lantern
```
- `<quest>.IsActive` — 퀘스트가 진행 중.
- `<quest>.Status` — `0` 시작 안 함, `1` 진행 중, `2` 완료.
- `<quest>.DataStatus` — 현재 단계.
- `<quest>.hasTag("tag")`, `<quest>.notHasTag("tag")` — Cthangover는 이것으로 장면의 어떤 시나리오를 재생할지 고릅니다. 예: `AwakeningQuest.hasTag("book_taken")`.
## 문제가 생겼을 때
1. **퀘스트가 저널에 없습니다.** 상태가 `Progress`(완료 탭이라면 `End`)여야 합니다. 단계만 설정해서는 부족합니다.
2. **저널이 텍스트 대신 키를 보여 줍니다.** 단계의 키를 mod의 `locale` 파일에 추가하세요.
3. **조건이 항상 거짓입니다.** 퀘스트 id의 철자가 퀘스트 파일의 `Id`와 다릅니다. 로그에 알 수 없는 퀘스트 경고가 기록됩니다.
+81
View File
@@ -0,0 +1,81 @@
# Quests Engine — задания, их шаги и журнал
Quests Engine ведёт счёт задачам игрока. У задания есть название и нумерованный список шагов; сценарии берут его в работу, переводят на следующий шаг, отмечают тегами и завершают. Панель **Журнал** показывает задания, которые взял игрок, а их состояние игра сохраняет.
Его используют Cthangover (пробуждение в прологе и старый дом) и RPG Plus (лесные задания).
## Журнал
Открывается иконкой журнала на панели инструментов. Пока игрок не взял ни одного задания, журнал пуст:
![Журнал в RPG Plus на старте: вкладки «Активные» и «Завершённые», на обеих страницах «Заданий нет».](assets/journal-before.jpg)
В RPG Plus первое задание даёт староста деревни. Спросите его, куда идти:
![Дом старосты: герой перед старостой, справа два варианта — «Волк умеет гасить фонари?» и «Где его искать?».](assets/elder-choice.jpg)
После ответа задание появляется в журнале:
![Журнал после разговора: «Свет по ведомости» в списке активных; справа «Запись II из V», первый шаг зачёркнут, текущий шаг — «Прогони волка у пещеры на востоке леса. Найди янтарное сердце».](assets/journal-after.jpg)
- **Активные** — список заданий в работе, **Завершённые** — законченных. Ещё не начатые задания не появляются никогда.
- Правая страница показывает выбранное задание: выполненные шаги зачёркнуты, текущий отмечен, а будущие скрыты — журнал не раскрывает сюжет заранее.
- Заработанные заданием теги показаны под записью маленькими золотыми метками.
## Описание задания
Задания — это JSON-файлы вида `quest` в папке `quests/` мода. Вот задание с картинок (из RPG Plus):
```json
{
"Kind": "quest",
"Items": [
{
"Id": "woodland_ward",
"Name": "rpg_plus/quest/ward/name",
"StatusToDescription": {
"0": "rpg_plus/quest/ward/0",
"1": "rpg_plus/quest/ward/1",
"2": "rpg_plus/quest/ward/2",
"3": "rpg_plus/quest/ward/3",
"4": "rpg_plus/quest/ward/4"
}
}
]
}
```
`Name` и каждый шаг — ключи перевода. Числа — это **шаги** задания: на шаге 1 текст `1` показан как текущий, а `0` — зачёркнутым; на картинке это «Запись II из V».
## Как сценарий двигает задание
Ответ старосты в RPG Plus запускает задание и ставит его на шаг 1:
```scenario
action quest.set_status quest_id=woodland_ward status=Progress
action quest.set_data_status quest_id=woodland_ward level=1
```
- `quest.set_status` — состояние задания: `NotStarted`, `Progress` (активно) или `End` (завершено).
- `quest.set_data_status` — текущий шаг, `level` — его номер.
- `quest.add_tag` / `quest.remove_tag` с `tag=…` — запомнить случившееся, например, какой предмет игрок взял первым.
- `quest.send_notification` — показывает игроку уведомление о задании; само по себе изменение задания уведомления не даёт.
## Как проверить задание
Проверки задания работают везде, где игра принимает условие: в `when`, в условиях ответов, условиях сцен и событиях карты.
```scenario
when "woodland_ward.DataStatus >= 2" -> :lantern
```
- `<quest>.IsActive` — задание в работе;
- `<quest>.Status` — `0` не начато, `1` в работе, `2` завершено;
- `<quest>.DataStatus` — текущий шаг;
- `<quest>.hasTag("tag")`, `<quest>.notHasTag("tag")` — так Cthangover выбирает, какой сценарий сцены играть, например `AwakeningQuest.hasTag("book_taken")`.
## Если что-то пошло не так
1. **Задания нет в журнале.** Его состояние должно быть `Progress` (или `End` для вкладки завершённых); одной установки шага мало.
2. **Журнал показывает ключ вместо текста.** Добавьте ключ шага в файлы `locale` мода.
3. **Условие всегда ложно.** Идентификатор задания написан иначе, чем `Id` в файле задания; в логе будет предупреждение о неизвестном задании.
+81
View File
@@ -0,0 +1,81 @@
# Quests Engine — nhiệm vụ, các bước và nhật ký
Quests Engine quản lý các việc người chơi phải làm. Một nhiệm vụ có tên và danh sách các bước được đánh số; kịch bản khởi đầu nhiệm vụ, đưa nó sang bước tiếp, gắn thẻ và kết thúc nó. Bảng **Nhật ký** hiển thị những nhiệm vụ người chơi đã nhận, và game lưu trạng thái của chúng.
Cthangover (tỉnh dậy trong prologue và ngôi nhà cũ) và RPG Plus (các nhiệm vụ trong rừng) đều dùng mod này.
## Nhật ký
Mở bằng biểu tượng nhật ký trên thanh công cụ. Khi người chơi chưa nhận nhiệm vụ nào, nhật ký còn trống:
![Nhật ký của RPG Plus lúc đầu: hai thẻ Đang làm và Đã xong, cả hai trang đều ghi "Chưa có nhiệm vụ".](assets/journal-before.jpg)
Trong RPG Plus, trưởng làng giao nhiệm vụ đầu tiên. Hỏi ông xem nên đi tìm ở đâu:
![Nhà trưởng làng: anh hùng đứng trước trưởng làng, hai lựa chọn bên phải — "Sói tắt được đèn sao?" và "Tìm nó ở đâu?".](assets/elder-choice.jpg)
Sau câu trả lời, nhiệm vụ xuất hiện trong nhật ký:
![Nhật ký sau cuộc trò chuyện: "Ngọn đèn trên sổ sách" nằm trong danh sách đang làm; bên phải là "Mục II trên V", bước đầu đã bị gạch, bước hiện tại là "Đánh bại con sói bên hang trong rừng phía đông. Tìm trái tim hổ phách".](assets/journal-after.jpg)
- **Đang làm** liệt kê nhiệm vụ đang tiến hành, **Đã xong** liệt kê nhiệm vụ hoàn thành. Nhiệm vụ chưa bắt đầu không bao giờ hiện ra.
- Trang bên phải hiển thị nhiệm vụ đang chọn: các bước đã làm bị gạch ngang, bước hiện tại được đánh dấu, các bước sau còn ẩn — nhật ký không tiết lộ trước câu chuyện.
- Các thẻ nhiệm vụ đã giành được hiện dưới mục nhỏ, dạng nhãn vàng nhỏ.
## Định nghĩa nhiệm vụ
Nhiệm vụ là tệp JSON kind `quest` trong thư mục `quests/` của mod. Đây là nhiệm vụ trong các hình trên (thuộc RPG Plus):
```json
{
"Kind": "quest",
"Items": [
{
"Id": "woodland_ward",
"Name": "rpg_plus/quest/ward/name",
"StatusToDescription": {
"0": "rpg_plus/quest/ward/0",
"1": "rpg_plus/quest/ward/1",
"2": "rpg_plus/quest/ward/2",
"3": "rpg_plus/quest/ward/3",
"4": "rpg_plus/quest/ward/4"
}
}
]
}
```
`Name` và từng bước đều là khóa dịch. Các con số chính là **bước** của nhiệm vụ: ở bước 1, văn bản của `1` hiện là bước hiện tại và `0` bị gạch ngang — tức "Mục II trên V" trong hình.
## Đưa nhiệm vụ đi từ kịch bản
Câu trả lời của trưởng làng trong RPG Plus khởi đầu nhiệm vụ và đặt nó ở bước 1:
```scenario
action quest.set_status quest_id=woodland_ward status=Progress
action quest.set_data_status quest_id=woodland_ward level=1
```
- `quest.set_status` — trạng thái nhiệm vụ: `NotStarted`, `Progress` (đang làm) hoặc `End` (hoàn thành).
- `quest.set_data_status` — bước hiện tại, `level` là số của nó.
- `quest.add_tag` / `quest.remove_tag` kèm `tag=…` — ghi nhớ chuyện đã xảy ra, chẳng hạn người chơi lấy vật phẩm nào trước.
- `quest.send_notification` — hiện thông báo về nhiệm vụ cho người chơi; thay đổi nhiệm vụ thì tự nó không thông báo.
## Kiểm tra nhiệm vụ
Phép kiểm nhiệm vụ dùng được ở mọi nơi game nhận điều kiện: `when`, điều kiện lựa chọn, điều kiện cảnh và sự kiện bản đồ.
```scenario
when "woodland_ward.DataStatus >= 2" -> :lantern
```
- `<quest>.IsActive` — nhiệm vụ đang tiến hành;
- `<quest>.Status` — `0` chưa bắt đầu, `1` đang làm, `2` đã hoàn thành;
- `<quest>.DataStatus` — bước hiện tại;
- `<quest>.hasTag("tag")`, `<quest>.notHasTag("tag")` — Cthangover dùng chúng để chọn kịch bản nào của cảnh sẽ chạy, ví dụ `AwakeningQuest.hasTag("book_taken")`.
## Khi có trục trặc
1. **Nhiệm vụ không có trong nhật ký.** Trạng thái của nó phải là `Progress` (hoặc `End` để vào thẻ đã xong); chỉ đặt bước là chưa đủ.
2. **Nhật ký hiện khóa thay vì văn bản.** Thêm khóa của bước vào các tệp `locale` của mod.
3. **Điều kiện luôn sai.** Id nhiệm vụ viết khác với `Id` trong tệp nhiệm vụ; log sẽ cảnh báo về nhiệm vụ lạ.
+81
View File
@@ -0,0 +1,81 @@
# Quests Engine — 任务、任务步骤与日志
Quests Engine 替玩家记账。每个任务都有名称和编号的步骤列表;剧本负责开启任务、推进到下一步、打上标记并完成任务。**日志**面板显示玩家已领取的任务,游戏会保存它们的状态。
Cthangover(序章的苏醒和旧宅)与 RPG Plus(森林任务)都用到了它。
## 日志
用工具栏上的日志图标打开。玩家还没领取任何任务时,日志是空的:
![RPG Plus 开局时的日志:「进行中」和「已完成」两个页签,两页都写着「暂无任务」。](assets/journal-before.jpg)
在 RPG Plus 里,村庄的长老给出第一个任务。向他问问去哪里找:
![长老的家:主角站在长老面前,右侧有两个选项——「狼会熄灯吗?」和「去哪儿找它?」。](assets/elder-choice.jpg)
回答之后,任务就出现在日志里:
![对话后的日志:「账簿上的一盏灯」出现在进行中列表;右侧是「第 II 条,共 V 条」,第一步已划掉,当前步骤为「击退东部森林洞窟旁的狼。找到琥珀之心」。](assets/journal-after.jpg)
- **进行中**列出正在做的任务,**已完成**列出做完的。还没开始的任务永远不会出现。
- 右页显示选中的任务:已完成的步骤划掉,当前步骤做了标记,后续步骤保持隐藏——日志不会剧透后面的故事。
- 任务获得的标记会以小小的金色标签显示在条目下方。
## 任务的定义
任务是 mod 的 `quests/` 文件夹里类型为 `quest` 的 JSON 文件。这就是截图中的任务(来自 RPG Plus):
```json
{
"Kind": "quest",
"Items": [
{
"Id": "woodland_ward",
"Name": "rpg_plus/quest/ward/name",
"StatusToDescription": {
"0": "rpg_plus/quest/ward/0",
"1": "rpg_plus/quest/ward/1",
"2": "rpg_plus/quest/ward/2",
"3": "rpg_plus/quest/ward/3",
"4": "rpg_plus/quest/ward/4"
}
}
]
}
```
`Name` 和每个步骤都是翻译键。数字就是任务的**步骤**:在第 1 步时,`1` 的文本显示为当前步骤,`0` 则划掉——即截图中的「第 II 条,共 V 条」。
## 从剧本推进任务
RPG Plus 中长老的回答会开启任务并把它放到第 1 步:
```scenario
action quest.set_status quest_id=woodland_ward status=Progress
action quest.set_data_status quest_id=woodland_ward level=1
```
- `quest.set_status` — 任务的状态:`NotStarted`、`Progress`(进行中)或 `End`(已完成)。
- `quest.set_data_status` — 当前步骤,`level` 是它的编号。
- `quest.add_tag` / `quest.remove_tag` 配合 `tag=…` — 记下发生过的事,比如玩家先拿了哪个物品。
- `quest.send_notification` — 向玩家弹出任务通知;改变任务本身不会触发通知。
## 检查任务
凡是游戏接受条件的地方都能用任务检查:`when`、选项条件、场景条件和地图事件。
```scenario
when "woodland_ward.DataStatus >= 2" -> :lantern
```
- `<quest>.IsActive` — 任务正在进行;
- `<quest>.Status` — `0` 未开始,`1` 进行中,`2` 已完成;
- `<quest>.DataStatus` — 当前步骤;
- `<quest>.hasTag("tag")`、`<quest>.notHasTag("tag")` — Cthangover 用它们决定场景播放哪段剧本,例如 `AwakeningQuest.hasTag("book_taken")`。
## 出问题时
1. **任务不在日志里。** 它的状态必须是 `Progress`(或在「已完成」页签显示则用 `End`);只设置步骤是不够的。
2. **日志显示的是键而不是文本。** 把步骤的键加进 mod 的 `locale` 文件。
3. **条件永远为假。** 写的任务 id 与任务文件里的 `Id` 不一致;日志会警告存在未知任务。
+1 -1
View File
@@ -1,4 +1,4 @@
mod_quests_base_name = Quests Engine mod_quests_base_name = Quests Engine
mod_quests_base_desc = Engine quests subsystem: the quest factory and runtime state, the IQuestService implementation, quest scenario actions, quest scene conditions and the quest journal UI. mod_quests_base_desc = Quests engine: quests with numbered steps that scenarios start, advance and finish, and the journal panel that shows them.
ui/journal/new = New journal entry ui/journal/new = New journal entry
ui/journal/updated = Quest updated ui/journal/updated = Quest updated
+4
View File
@@ -0,0 +1,4 @@
mod_quests_base_name = Motor de misiones
mod_quests_base_desc = Motor de misiones: misiones con pasos numerados que los escenarios inician, avanzan y completan, y el panel del diario que las muestra.
ui/journal/new = Nueva entrada en el diario
ui/journal/updated = Misión actualizada
+4
View File
@@ -0,0 +1,4 @@
mod_quests_base_name = クエストエンジン
mod_quests_base_desc = クエストエンジン: シナリオが開始・進行・完了させる番号付きステップのクエストと、それらを表示するジャーナルパネル。
ui/journal/new = 日誌に新しい記録
ui/journal/updated = クエストが更新されました
+4
View File
@@ -0,0 +1,4 @@
mod_quests_base_name = 퀘스트 엔진
mod_quests_base_desc = 퀘스트 엔진: 시나리오가 시작하고 진행하고 완료하는 번호 붙은 단계의 퀘스트와 이를 보여 주는 저널 패널.
ui/journal/new = 새 일지 항목
ui/journal/updated = 퀘스트 갱신됨
+1 -1
View File
@@ -1,4 +1,4 @@
mod_quests_base_name = Движок квестов mod_quests_base_name = Движок квестов
mod_quests_base_desc = Подсистема квестов движка: фабрика квестов и их состояние, реализация IQuestService, сценарные действия, условия квестов в сценах и журнал квестов. mod_quests_base_desc = Движок заданий: задания с пронумерованными шагами, которые сценарии запускают, ведут дальше и завершают, и панель журнала, где они видны.
ui/journal/new = Новая запись в журнале ui/journal/new = Новая запись в журнале
ui/journal/updated = Задание обновлено ui/journal/updated = Задание обновлено
+14
View File
@@ -0,0 +1,14 @@
quests/schema/builtin/quest_status = Quest status
quests/schema/builtin/quest_status_desc = Moves a quest through its stages
quests/schema/field/quest = Quest
quests/schema/field/status = Status
quests/schema/builtin/quest_tag = Quest tag
quests/schema/builtin/quest_tag_desc = Marks what happened in a quest
quests/schema/field/tag = Tag
quests/schema/builtin/quest_remove_tag = Remove a quest tag
quests/schema/builtin/quest_remove_tag_desc = Takes off a mark set earlier
quests/schema/builtin/quest_data_status = Quest stage
quests/schema/builtin/quest_data_status_desc = The stage number inside a quest: which journal text to show
quests/schema/field/stage = Stage
quests/schema/builtin/quest_notify = Quest notification
quests/schema/builtin/quest_notify_desc = A toast with the quest's title
+14
View File
@@ -0,0 +1,14 @@
quests/schema/builtin/quest_status = Estado de misión
quests/schema/builtin/quest_status_desc = Hace avanzar una misión por sus etapas
quests/schema/field/quest = Misión
quests/schema/field/status = Estado
quests/schema/builtin/quest_tag = Etiqueta de misión
quests/schema/builtin/quest_tag_desc = Marca lo que pasó en una misión
quests/schema/field/tag = Etiqueta
quests/schema/builtin/quest_remove_tag = Quitar una etiqueta de misión
quests/schema/builtin/quest_remove_tag_desc = Quita una marca puesta antes
quests/schema/builtin/quest_data_status = Etapa de misión
quests/schema/builtin/quest_data_status_desc = El número de etapa dentro de una misión: qué texto del diario mostrar
quests/schema/field/stage = Etapa
quests/schema/builtin/quest_notify = Aviso de misión
quests/schema/builtin/quest_notify_desc = Un aviso con el título de la misión
+14
View File
@@ -0,0 +1,14 @@
quests/schema/builtin/quest_status = クエストの状態
quests/schema/builtin/quest_status_desc = クエストの段階を進める
quests/schema/field/quest = クエスト
quests/schema/field/status = ステータス値
quests/schema/builtin/quest_tag = クエストのタグ
quests/schema/builtin/quest_tag_desc = クエストで起きたことを記す
quests/schema/field/tag = タグ
quests/schema/builtin/quest_remove_tag = クエストのタグを外す
quests/schema/builtin/quest_remove_tag_desc = 以前付けた印を外す
quests/schema/builtin/quest_data_status = クエストの段階
quests/schema/builtin/quest_data_status_desc = クエスト内の段階番号:日誌のどの文を出すか
quests/schema/field/stage = 段階
quests/schema/builtin/quest_notify = クエストの通知
quests/schema/builtin/quest_notify_desc = クエスト名の通知
+14
View File
@@ -0,0 +1,14 @@
quests/schema/builtin/quest_status = 퀘스트 상태
quests/schema/builtin/quest_status_desc = 퀘스트 단계를 진행
quests/schema/field/quest = 퀘스트
quests/schema/field/status = 상태
quests/schema/builtin/quest_tag = 퀘스트 태그
quests/schema/builtin/quest_tag_desc = 퀘스트에서 일어난 일을 표시
quests/schema/field/tag = 태그
quests/schema/builtin/quest_remove_tag = 퀘스트 태그 제거
quests/schema/builtin/quest_remove_tag_desc = 앞서 단 표시를 뗍니다
quests/schema/builtin/quest_data_status = 퀘스트 단계
quests/schema/builtin/quest_data_status_desc = 퀘스트 안의 단계 번호: 일지의 어느 글을 보일지
quests/schema/field/stage = 단계
quests/schema/builtin/quest_notify = 퀘스트 알림
quests/schema/builtin/quest_notify_desc = 퀘스트 제목 알림
+14
View File
@@ -0,0 +1,14 @@
quests/schema/builtin/quest_status = Статус квеста
quests/schema/builtin/quest_status_desc = Двигает квест по этапам
quests/schema/field/quest = Квест
quests/schema/field/status = Статус
quests/schema/builtin/quest_tag = Метка квеста
quests/schema/builtin/quest_tag_desc = Отмечает, что в квесте случилось
quests/schema/field/tag = Метка
quests/schema/builtin/quest_remove_tag = Снять метку квеста
quests/schema/builtin/quest_remove_tag_desc = Убирает отметку, поставленную раньше
quests/schema/builtin/quest_data_status = Этап квеста
quests/schema/builtin/quest_data_status_desc = Номер этапа внутри квеста: какой текст журнала показывать
quests/schema/field/stage = Этап
quests/schema/builtin/quest_notify = Напомнить о квесте
quests/schema/builtin/quest_notify_desc = Всплывающее уведомление с названием квеста
+14
View File
@@ -0,0 +1,14 @@
quests/schema/builtin/quest_status = Trạng thái nhiệm vụ
quests/schema/builtin/quest_status_desc = Đẩy nhiệm vụ qua các giai đoạn
quests/schema/field/quest = Nhiệm vụ
quests/schema/field/status = Trạng thái
quests/schema/builtin/quest_tag = Thẻ nhiệm vụ
quests/schema/builtin/quest_tag_desc = Đánh dấu điều đã xảy ra trong nhiệm vụ
quests/schema/field/tag = Thẻ
quests/schema/builtin/quest_remove_tag = Gỡ thẻ nhiệm vụ
quests/schema/builtin/quest_remove_tag_desc = Bỏ một dấu đã đặt trước đó
quests/schema/builtin/quest_data_status = Giai đoạn nhiệm vụ
quests/schema/builtin/quest_data_status_desc = Số giai đoạn trong nhiệm vụ: hiện đoạn nhật ký nào
quests/schema/field/stage = Giai đoạn
quests/schema/builtin/quest_notify = Thông báo nhiệm vụ
quests/schema/builtin/quest_notify_desc = Thông báo kèm tên nhiệm vụ
+14
View File
@@ -0,0 +1,14 @@
quests/schema/builtin/quest_status = 任务状态
quests/schema/builtin/quest_status_desc = 推进任务阶段
quests/schema/field/quest = 任务
quests/schema/field/status = 状态
quests/schema/builtin/quest_tag = 任务标签
quests/schema/builtin/quest_tag_desc = 标记任务中发生了什么
quests/schema/field/tag = 标签
quests/schema/builtin/quest_remove_tag = 移除任务标签
quests/schema/builtin/quest_remove_tag_desc = 去掉之前设置的标记
quests/schema/builtin/quest_data_status = 任务阶段
quests/schema/builtin/quest_data_status_desc = 任务内的阶段编号:显示哪段日志文本
quests/schema/field/stage = 阶段
quests/schema/builtin/quest_notify = 任务提示
quests/schema/builtin/quest_notify_desc = 显示任务名称的提示
+4
View File
@@ -0,0 +1,4 @@
mod_quests_base_name = Engine nhiệm vụ
mod_quests_base_desc = Engine nhiệm vụ: các nhiệm vụ có bước đánh số mà kịch bản khởi đầu, đưa tiến và kết thúc, cùng bảng nhật ký hiển thị chúng.
ui/journal/new = Mục nhật ký mới
ui/journal/updated = Nhiệm vụ đã cập nhật
+4
View File
@@ -0,0 +1,4 @@
mod_quests_base_name = 任务引擎
mod_quests_base_desc = 任务引擎:由剧本开启、推进并完成的分步任务,以及展示它们的日志面板。
ui/journal/new = 新的日志条目
ui/journal/updated = 任务已更新
+1 -1
View File
@@ -3,7 +3,7 @@
"name": "Quests Engine", "name": "Quests Engine",
"version": "1.0.0", "version": "1.0.0",
"author": "ct", "author": "ct",
"description": "Engine quests subsystem: the quest factory and runtime state (QuestFactory, QuestBase/QuestData), the IQuestService implementation, quest scenario actions, quest scene conditions with the QuestParser leaf parser and the quest journal UI. Replaces the former Core/Quests state, Core/Actions quest services and actions, Core/Scenes quest conditions and Core/UI/Quests - QuestsModInitializer publishes the kernel contract (IQuestService via QuestServiceRegistry), registers the quest leaf parser and the new-game resettable; QuestsSaveable persists quest state through the generic mod save slot.", "description": "Quests engine: quests with numbered steps that scenarios start, advance and finish, and the journal panel that shows them.",
"category": "engine, library", "category": "engine, library",
"sources": [ "sources": [
"src/**/*.cs" "src/**/*.cs"
+108
View File
@@ -0,0 +1,108 @@
{
"Actions": [
{
"Id": "quest.set_status",
"Name": "quests/schema/builtin/quest_status",
"Description": "quests/schema/builtin/quest_status_desc",
"Category": "quests",
"Params": [
{
"Key": "quest_id",
"Type": "ref",
"Kind": "quest",
"Required": true,
"Name": "quests/schema/field/quest"
},
{
"Key": "status",
"Type": "choice",
"Options": [
"NotStarted",
"Progress",
"End"
],
"Required": true,
"Name": "quests/schema/field/status"
}
]
},
{
"Id": "quest.add_tag",
"Name": "quests/schema/builtin/quest_tag",
"Description": "quests/schema/builtin/quest_tag_desc",
"Category": "quests",
"Params": [
{
"Key": "quest_id",
"Type": "ref",
"Kind": "quest",
"Required": true,
"Name": "quests/schema/field/quest"
},
{
"Key": "tag",
"Type": "text",
"Required": true,
"Name": "quests/schema/field/tag"
}
]
},
{
"Id": "quest.remove_tag",
"Name": "quests/schema/builtin/quest_remove_tag",
"Description": "quests/schema/builtin/quest_remove_tag_desc",
"Category": "quests",
"Params": [
{
"Key": "quest_id",
"Type": "ref",
"Kind": "quest",
"Required": true,
"Name": "quests/schema/field/quest"
},
{
"Key": "tag",
"Type": "text",
"Required": true,
"Name": "quests/schema/field/tag"
}
]
},
{
"Id": "quest.set_data_status",
"Name": "quests/schema/builtin/quest_data_status",
"Description": "quests/schema/builtin/quest_data_status_desc",
"Category": "quests",
"Params": [
{
"Key": "quest_id",
"Type": "ref",
"Kind": "quest",
"Required": true,
"Name": "quests/schema/field/quest"
},
{
"Key": "level",
"Type": "int",
"Required": true,
"Name": "quests/schema/field/stage"
}
]
},
{
"Id": "quest.send_notification",
"Name": "quests/schema/builtin/quest_notify",
"Description": "quests/schema/builtin/quest_notify_desc",
"Category": "quests",
"Params": [
{
"Key": "quest_id",
"Type": "ref",
"Kind": "quest",
"Required": true,
"Name": "quests/schema/field/quest"
}
]
}
]
}