Draw broken objects as fragments, plane tiles for fences and walls, tileset publishing; mod documentation

This commit is contained in:
cthangover committed 2026-10-29 09:26:10 +01:00
1 parent e153dc9b15
commit 7b28c1bb0a
74 files changed
+2782 -886

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

+95
View File
@@ -0,0 +1,95 @@
# RPG World — walk a tile map, talk, open, fight
RPG World turns a game into a tile-map RPG in the spirit of classic 2D role-playing games: you walk a grid map with the keyboard, talk to people, open chests, step through doors and fight monsters, then come back to the same spot. A map is an ordinary scene of the game, so the dialog box, scenarios, saving, music and time of day all work on maps as they do in a visual novel.
It powers the village, forest and desert of **RPG Plus**. The maps and people themselves come from content mods such as RPG Demo; this mod supplies the rules.
![Exploring the village in RPG Plus: the map name at the top left, the toolbar at the top right, the controls hint at the bottom left.](assets/village.jpg)
## How to play on a map
- **Walk** with WASD or the arrow keys; hold **Shift** to run.
- **Act** with **E** or **F**: talk to the person you face, open the chest, read the sign.
- **Step** onto a doorway or a map edge to go to the next map.
- **Random battles** can start as you walk in some places, such as the forest.
- After a battle you are back on the same cell of the same map.
- The game saves where you stand; loading puts you back there.
The cell you can act on is framed, and the hint at the bottom left changes to **E / F · Interact**.
## Example: a chest that stays open
The chest in the elder's house is two events on the same cell. The closed one shows while the story flag `rpg_house_chest` is not set; its scenario gives three coins and sets the flag. From then on the open chest shows instead.
![Before: the hero next to the closed chest in the elder's house at noon.](assets/chest-before.jpg)
![The chest's text: old socks, a note saying "Don't touch", and three coins underneath.](assets/chest-text.jpg)
![After: the same cell now shows the open chest, framed by the interaction marker; the hint at the bottom left reads "E / F · Interact".](assets/chest-after.jpg)
```json
{ "Id": "chest", "X": 9, "Y": 7, "Tile": 14,
"Scenario": "rpg_demo/events/house_chest",
"Condition": "rpg_house_chest != 1" },
{ "Id": "chest_open", "X": 9, "Y": 7, "Tile": 15,
"Scenario": "rpg_demo/events/chest_empty",
"Condition": "rpg_house_chest == 1" }
```
```scenario
ptext "In the chest: old socks and a note saying 'Don't touch'. Too late. Under the socks: three coins." key=rpg_demo/chest/house
action item.add id=money/coin count=3
flag rpg_house_chest 1
end
```
## For authors: maps
A map is a JSON file in a mod's `maps/` folder, plus a scene with the same name in `scenes/` for its background in battles and its ambience.
- **Three drawn layers**, each a list of rows of tile numbers (`.` for empty): `Back` — ground, floors, water; `Main` — objects at the characters' level: walls, trunks, fences; `Front` — drawn over the characters: tree crowns, eaves, arches.
- **Collision** — a row layer that overrides the tiles' own passability where needed: an invisible wall at a cliff edge or a gap in a hedge.
- **Tileset** — the tile atlas and the properties of its tiles (solid or not, surfaces, objects).
- **Spawn** — where a new arrival appears; **Zoom**; optional **Ambient** colour for interiors (otherwise the time of day lights the map) and **Atmosphere** (`woodland` adds leaves, fireflies and water ripples).
- **Encounters** — random battles: on average one per `Steps` steps, against one of the `Groups`.
```json
"Encounters": { "Steps": 48, "Groups": ["rpg_slime", "rpg_slime,rpg_slime"] }
```
## For authors: events
Events live in `map_events/<map id>/*.json` of any mod. An event has a **look** and an **effect**, chosen independently:
- look: a character `Sprite`, a single atlas `Tile`, an item `Icon` lying on the ground, or nothing (an invisible trigger);
- effect: a `Teleport` to a cell of this or another map, or a `Scenario` followed by optional inline `Commands` — the full scenario language, including `action rpg.battle`, flags and quests;
- `Trigger`: `Action` (E/F while facing it) or `Touch` (stepping onto it);
- `Solid`: whether it blocks the way (by default, drawn events do);
- `Condition`: hide the event unless the condition holds;
- `Pages`: alternative looks and effects, each with its own condition — the last page whose condition holds is used;
- `Route`: autonomous movement such as `{"Steps": ["left", "wait", "right"], "Every": 0.8}` with `up`/`down`/`left`/`right`, `random`, `toward`/`away` (from the player), `wait` and `face_…`;
- `Light`: a glow around the event, `{"Radius": 3, "Color": "#ffd8a0"}`, seen at dusk and night.
**Add to or change another mod's map.** Event files are merged in load order: a new `Id` adds an event to that map, and the same `Id` from a mod that depends on the owner replaces it. This is how RPG Plus gives the demo's elder new dialogs.
## Scenario actions
```scenario
action rpg.battle enemies=rpg_wolf,rpg_slime win_flag=rpg_wolf_dead
action rpg.teleport map=rpg_forest x=1 y=8 dir=right
```
- `rpg.battle` starts a battle with the game's battle core and returns to the same cell; on victory `win_flag` is set to 1, so a map monster whose condition tests that flag disappears. End the scenario after it.
- `rpg.teleport` moves the player to a cell, on this map or another one.
## Game settings
- **Appearance** (`rpg.player_charset`) — the hero's sprite on maps, chosen from the charsets in the game.
- **Map projection** (`tile.renderer`) — top-down or isometric; see Tile Rendering.
## If something goes wrong
1. **A person or chest does not react.** Face it and press E or F; a `Touch` event reacts only when you step on it.
2. **A monster or chest comes back.** Its `Condition` must test the flag that its scenario or `win_flag` sets.
3. **You cannot walk somewhere that looks open.** A solid tile or the map's collision layer blocks that cell.
4. **No battle background.** The map's scene in `scenes/<map>.json` needs a `defaultBackground`.
+95
View File
@@ -0,0 +1,95 @@
# RPG World — camina por un mapa de tiles, habla, abre, lucha
RPG World convierte un juego en un RPG de mapas de tiles al estilo de los rol clásicos en 2D: avanzas por una cuadrícula con el teclado, hablas con la gente, abres cofres, cruzas puertas y luchas contra monstruos, y tras el combate vuelves al mismo punto. El mapa es una escena cualquiera del juego, así que el cuadro de diálogo, los escenarios, el guardado, la música y la hora del día funcionan en los mapas igual que en una novela visual.
Este mod da vida a la aldea, el bosque y el desierto de **RPG Plus**. Los mapas y sus habitantes vienen de mods de contenido como RPG Demo; este aporta las reglas.
![Explorando la aldea de RPG Plus: el nombre del mapa arriba a la izquierda, la barra de herramientas arriba a la derecha y la ayuda de controles abajo a la izquierda.](assets/village.jpg)
## Cómo jugar en un mapa
- **Camina** con WASD o las flechas; mantén pulsado **Shift** para correr.
- **Actúa** con **E** o **F**: habla con quien tengas delante, abre el cofre, lee el cartel.
- **Pisa** una puerta o el borde del mapa para pasar al siguiente.
- En algunos sitios, como el bosque, los **combates aleatorios** pueden empezar mientras caminas.
- Tras un combate vuelves a la misma casilla del mismo mapa.
- El juego guarda tu posición; al cargar reapareces exactamente ahí.
La casilla con la que puedes interactuar se enmarca, y la ayuda de abajo a la izquierda cambia a **E / F · Interact**.
## Ejemplo: un cofre que sigue abierto
El cofre de la casa del anciano son dos eventos en la misma casilla. El cerrado se muestra mientras la bandera de historia `rpg_house_chest` no esté activa; su escenario entrega tres monedas y activa la bandera. A partir de entonces se muestra en su lugar el cofre abierto.
![Antes: el héroe junto al cofre cerrado en la casa del anciano, al mediodía.](assets/chest-before.jpg)
![El texto del cofre: calcetines viejos, una nota de «No tocar» y tres monedas debajo.](assets/chest-text.jpg)
![Después: la misma casilla muestra ahora el cofre abierto, enmarcado por el marcador de interacción; la ayuda de abajo a la izquierda dice «E / F · Interact».](assets/chest-after.jpg)
```json
{ "Id": "chest", "X": 9, "Y": 7, "Tile": 14,
"Scenario": "rpg_demo/events/house_chest",
"Condition": "rpg_house_chest != 1" },
{ "Id": "chest_open", "X": 9, "Y": 7, "Tile": 15,
"Scenario": "rpg_demo/events/chest_empty",
"Condition": "rpg_house_chest == 1" }
```
```scenario
ptext "En el cofre: calcetines viejos y una nota que dice "No tocar". Demasiado tarde. Debajo de los calcetines: tres monedas." key=rpg_demo/chest/house
action item.add id=money/coin count=3
flag rpg_house_chest 1
end
```
## Para autores: mapas
Un mapa es un archivo JSON en la carpeta `maps/` de un mod, más una escena con el mismo nombre en `scenes/` para su fondo en los combates y su ambiente sonoro.
- **Tres capas dibujadas**, cada una una lista de filas con números de tile (`.` para vacío): `Back` — suelo, interiores, agua; `Main` — objetos a la altura de los personajes: muros, troncos, vallas; `Front` — se dibuja sobre los personajes: copas de los árboles, aleros, arcos.
- **Colisiones** — una capa de filas que sustituye la transitabilidad de los tiles donde hace falta: un muro invisible al borde de un acantilado o un hueco en un seto.
- **Tileset** — el atlas de tiles y las propiedades de cada uno (sólido o no, superficies, objetos).
- **Spawn** — dónde aparece quien llega nuevo; **Zoom**; el color **Ambient** opcional para interiores (si no, la hora del día ilumina el mapa) y **Atmosphere** (`woodland` añade hojas, luciérnagas y ondas en el agua).
- **Encounters** — combates aleatorios: de media uno cada `Steps` pasos contra uno de los `Groups`.
```json
"Encounters": { "Steps": 48, "Groups": ["rpg_slime", "rpg_slime,rpg_slime"] }
```
## Para autores: eventos
Los eventos viven en `map_events/<id del mapa>/*.json` de cualquier mod. Un evento tiene un **aspecto** y un **efecto**, elegidos por separado:
- aspecto: un `Sprite` de personaje, un `Tile` suelto del atlas, el `Icon` de un objeto tirado en el suelo o nada (un desencadenante invisible);
- efecto: un `Teleport` a una casilla de este u otro mapa, o un `Scenario` seguido de `Commands` en línea opcionales — el lenguaje de escenarios completo, con `action rpg.battle`, banderas y misiones incluidas;
- `Trigger`: `Action` (E/F estando de cara) o `Touch` (al pisarlo);
- `Solid`: si bloquea el paso (por defecto, los eventos dibujados sí lo hacen);
- `Condition`: oculta el evento mientras no se cumpla la condición;
- `Pages`: aspectos y efectos alternativos, cada uno con su condición; se usa la última página cuya condición se cumpla;
- `Route`: movimiento autónomo como `{"Steps": ["left", "wait", "right"], "Every": 0.8}`, con `up`/`down`/`left`/`right`, `random`, `toward`/`away` (hacia el jugador o alejándose), `wait` y `face_…`;
- `Light`: un brillo alrededor del evento, `{"Radius": 3, "Color": "#ffd8a0"}`, visible al anochecer y de noche.
**Añade o cambia el mapa de otro mod.** Los archivos de eventos se combinan en orden de carga: un `Id` nuevo añade un evento al mapa, y el mismo `Id` de un mod que dependa del dueño lo sustituye. Así da RPG Plus nuevos diálogos al anciano de la demo.
## Acciones de escenario
```scenario
action rpg.battle enemies=rpg_wolf,rpg_slime win_flag=rpg_wolf_dead
action rpg.teleport map=rpg_forest x=1 y=8 dir=right
```
- `rpg.battle` inicia un combate con el núcleo de combate del juego y vuelve a la misma casilla; al ganar, `win_flag` pasa a 1, así que el monstruo del mapa cuya condición comprueba esa bandera desaparece. Termina el escenario después de esta acción.
- `rpg.teleport` mueve al jugador a una casilla de este mapa o de otro.
## Ajustes del juego
- **Apariencia** (`rpg.player_charset`) — el sprite del héroe en los mapas, elegido entre los charsets del juego.
- **Proyección del mapa** (`tile.renderer`) — vista superior o isométrica; ver Tile Rendering.
## Si algo falla
1. **Un personaje o un cofre no reacciona.** Colócate de frente y pulsa E o F; un evento `Touch` solo responde al pisarlo.
2. **Un monstruo o un cofre vuelve a aparecer.** Su `Condition` debe comprobar la bandera que activa su propio escenario o `win_flag`.
3. **No puedes pasar por un sitio que parece libre.** Esa casilla la bloquea un tile sólido o la capa de colisiones del mapa.
4. **No hay fondo de combate.** La escena del mapa en `scenes/<map>.json` necesita un `defaultBackground`.
+95
View File
@@ -0,0 +1,95 @@
# RPG World — タイルマップを歩き、話し、開け、戦う
RPG World は、ゲームをクラシックな 2D RPG の趣のあるタイルマップ式 RPG に変えます。キーボードでマス目状のマップを歩き、人と話し、宝箱を開け、ドアをくぐり、モンスターと戦う——そして戦いのあとは元の場所へ戻ります。マップはゲームのごく普通のシーンなので、会話ウィンドウもシナリオもセーブも音楽も時間の流れも、ビジュアルノベルと同じようにマップ上で働きます。
**RPG Plus** の村、森、砂漠はこの仕組みで動いています。マップや登場人物そのものは RPG Demo のようなコンテンツ Mod が担い、この Mod がルールを提供します。
![RPG Plus で村を探索したところ。左上にマップ名、右上にツールバー、左下に操作ヒント。](assets/village.jpg)
## マップでの遊び方
- **移動**は WASD か矢印キー。**Shift** を押している間は走ります。
- **操作**は **E** または **F**。向いている人に話しかける、宝箱を開ける、看板を読む。
- **ドアやマップの端に歩いて乗ると**、次のマップへ移動します。
- 場所によっては、歩いているだけで**ランダムエンカウント**が起こります(森など)。
- 戦闘が終わると、同じマップの同じマスへ戻ります。
- ゲームは立っている位置をセーブします。ロードすればそこへ戻れます。
操作できるマスは枠で囲まれ、左下のヒントが **E / F · Interact** に変わります。
## 例:開いたままの宝箱
長老の家の宝箱は、同じマスに置かれた 2 つのイベントです。ストーリーフラグ `rpg_house_chest` が立っていない間は閉じた宝箱が表示され、そのシナリオは硬貨 3 枚を渡してフラグを立てます。以降は、代わりに開いた宝箱が表示されます。
![変更前:正午の長老の家。閉じた宝箱のそばに主人公が立っている。](assets/chest-before.jpg)
![宝箱の中身のテキスト:古い靴下、「さわるな」というメモ、そしてその下の硬貨 3 枚。](assets/chest-text.jpg)
![変更後:同じマスには開いた宝箱が表示され、インタラクションマーカーの枠が付く。左下のヒントは「E / F · Interact」。](assets/chest-after.jpg)
```json
{ "Id": "chest", "X": 9, "Y": 7, "Tile": 14,
"Scenario": "rpg_demo/events/house_chest",
"Condition": "rpg_house_chest != 1" },
{ "Id": "chest_open", "X": 9, "Y": 7, "Tile": 15,
"Scenario": "rpg_demo/events/chest_empty",
"Condition": "rpg_house_chest == 1" }
```
```scenario
ptext "宝箱の中には古い靴下と「さわるな」と書かれたメモ。もう遅い。靴下の下には硬貨が 3 枚。" key=rpg_demo/chest/house
action item.add id=money/coin count=3
flag rpg_house_chest 1
end
```
## 作者向け:マップ
マップは Mod の `maps/` フォルダーにある JSON ファイルです。戦闘の背景と環境音のために、`scenes/` にも同名のシーンを置きます。
- **描画レイヤー 3 枚**。それぞれタイル番号の行のリスト(`.` は空)です。`Back` は地面・床・水、`Main` はキャラクターと同じ高さの物体(壁、幹、柵)、`Front` はキャラクターの上に描かれるもの(樹冠、軒、アーチ)。
- **衝突(コリジョン)** — 必要な場所でタイル自身の通行可否を上書きする行レイヤー。崖際の見えない壁や生け垣の抜け道に使います。
- **タイルセット** — タイルアトラスと、各タイルの属性(solid かどうか、地面の種類、物体)。
- **Spawn** — 新しく来た者が出現する位置。**Zoom**。屋内用の任意の **Ambient** カラー(なければ時間の流れがマップを照らします)。そして **Atmosphere**(`woodland` は落ち葉・蛍・水のさざ波を追加)。
- **Encounters** — ランダムエンカウント。平均して `Steps` 歩ごとに 1 回、`Groups` のいずれかと戦います。
```json
"Encounters": { "Steps": 48, "Groups": ["rpg_slime", "rpg_slime,rpg_slime"] }
```
## 作者向け:イベント
イベントは、どの Mod の `map_events/<マップ id>/*.json` にも置けます。イベントは**見た目**と**効果**を独立して選べます。
- 見た目:キャラクターの `Sprite`、アトラスの `Tile` 1 枚、地面に置いたアイテムの `Icon`、あるいは何もなし(見えないトリガー)。
- 効果:このマップか別のマップのマスへの `Teleport`、または `Scenario` とそこに書ける任意の `Commands`——`action rpg.battle`、フラグ、クエストを含むシナリオ言語のすべて。
- `Trigger`: `Action`(正面から E/F)か `Touch`(乗る)。
- `Solid`: 通行を妨げるか(描画されるイベントは既定で妨げます)。
- `Condition`: 条件を満たさない間、イベントを隠します。
- `Pages`: 条件つきの別の見た目と効果。条件を満たす最後のページが使われます。
- `Route`: 自律的な動き。`{"Steps": ["left", "wait", "right"], "Every": 0.8}` のように、`up`/`down`/`left`/`right`、`random`、`toward`/`away`(プレイヤーに向かって/離れて)、`wait`、`face_…` が使えます。
- `Light`: イベントのまわりの光。`{"Radius": 3, "Color": "#ffd8a0"}`。夕暮れと夜に見えます。
**他の Mod のマップに追加・変更を加える。** イベントファイルは読み込み順にマージされます。新しい `Id` はそのマップへイベントを追加し、所有者に依存する Mod が同じ `Id` を置けば置き換わります。RPG Plus がデモの長老に新しい会話を与えているのはこの仕組みです。
## シナリオアクション
```scenario
action rpg.battle enemies=rpg_wolf,rpg_slime win_flag=rpg_wolf_dead
action rpg.teleport map=rpg_forest x=1 y=8 dir=right
```
- `rpg.battle` はゲームのバトルコアで戦闘を始め、同じマスへ戻します。勝つと `win_flag` が 1 になるので、そのフラグを条件で見ているマップ上のモンスターは消えます。このアクションのあとでシナリオを終えてください。
- `rpg.teleport` はプレイヤーを、このマップまたは別のマップのマスへ移動させます。
## ゲーム設定
- **外見**(`rpg.player_charset`)— マップ上で主人公に使うスプライト。ゲームのチャーセットから選びます。
- **マップ投影**(`tile.renderer`)— トップダウンかアイソメトリック。Tile Rendering を参照。
## うまくいかないとき
1. **人物や宝箱が反応しない。** 正面から E か F を押してください。`Touch` イベントは乗ったときにしか反応しません。
2. **モンスターや宝箱が元に戻る。** その `Condition` は、シナリオや `win_flag` が立てるフラグを見ている必要があります。
3. **開けて見える場所を歩けない。** そのマスは solid なタイルかマップの衝突レイヤーに塞がれています。
4. **戦闘の背景がない。** `scenes/<map>.json` にあるマップのシーンに `defaultBackground` が必要です。
+95
View File
@@ -0,0 +1,95 @@
# RPG World — 타일 맵을 걷고, 말하고, 열고, 싸우기
RPG World는 게임을 클래식 2D 롤플레이 게임 스타일의 타일 맵 RPG로 바꿉니다. 키보드로 격자 맵을 걷고, 사람들과 대화하고, 상자를 열고, 문을 지나가고, 몬스터와 싸운 뒤 제자리로 돌아옵니다. 맵은 게임의 평범한 씬이므로 대화창, 시나리오, 저장, 음악, 시간대가 비주얼 노벨에서처럼 맵 위에서 똑같이 작동합니다.
**RPG Plus**의 마을, 숲, 사막이 이 엔진으로 돌아갑니다. 맵과 사람 자체는 RPG Demo 같은 콘텐츠 모드에서 나오며, 이 모드는 규칙을 담당합니다.
![RPG Plus에서 마을 탐험: 왼쪽 위 맵 이름, 오른쪽 위 툴바, 왼쪽 아래 조작 힌트.](assets/village.jpg)
## 맵에서 플레이하기
- **이동**은 WASD 또는 방향키입니다. **Shift**를 누르고 있으면 달립니다.
- **상호 작용**은 **E** 또는 **F**: 마주 본 사람과 대화하기, 상자 열기, 표지판 읽기.
- 문이나 맵 가장자리로 **걸어 들어가면** 다음 맵으로 넘어갑니다.
- 일부 지역(예: 숲)에서는 걷다가 **랜덤 전투**가 시작될 수 있습니다.
- 전투가 끝나면 같은 맵의 같은 칸으로 돌아옵니다.
- 게임은 서 있는 위치를 저장하며, 불러오면 그 자리로 돌아갑니다.
상호 작용할 수 있는 칸에는 테두리가 표시되고, 왼쪽 아래 힌트가 **E / F · Interact**로 바뀝니다.
## 예시: 열린 채로 있는 상자
장로의 집 상자는 같은 칸에 놓인 두 이벤트입니다. 스토리 플래그 `rpg_house_chest`가 설정되지 않은 동안은 닫힌 상자가 보이고, 그 시나리오는 동전 세 닢을 주며 플래그를 설정합니다. 이후에는 열린 상자가 대신 표시됩니다.
![이전: 정오의 장로의 집, 닫힌 상자 옆에 선 주인공.](assets/chest-before.jpg)
![상자의 문구: 낡은 양말, '만지지 마시오'라고 쓴 쪽지, 그 밑의 동전 세 닢.](assets/chest-text.jpg)
![이후: 같은 칸에 이제 열린 상자가 표시되고 상호 작용 마커 테두리가 둘러짐. 왼쪽 아래 힌트는 "E / F · Interact".](assets/chest-after.jpg)
```json
{ "Id": "chest", "X": 9, "Y": 7, "Tile": 14,
"Scenario": "rpg_demo/events/house_chest",
"Condition": "rpg_house_chest != 1" },
{ "Id": "chest_open", "X": 9, "Y": 7, "Tile": 15,
"Scenario": "rpg_demo/events/chest_empty",
"Condition": "rpg_house_chest == 1" }
```
```scenario
ptext "상자 안에는 낡은 양말과 '만지지 마시오'라고 쓴 쪽지. 이미 늦었다. 양말 밑에 동전 세 닢." key=rpg_demo/chest/house
action item.add id=money/coin count=3
flag rpg_house_chest 1
end
```
## 작성자용: 맵
맵은 모드의 `maps/` 폴더에 있는 JSON 파일이고, 전투 배경과 환경음을 위해 `scenes/`에 같은 이름의 씬도 하나 필요합니다.
- **그려지는 레이어 3개**, 각 레이어는 타일 번호 행의 목록(`.`은 빈 칸)입니다. `Back` — 지면, 바닥, 물 / `Main` — 캐릭터 높이의 물건: 벽, 나무줄기, 울타리 / `Front` — 캐릭터 위에 그려지는 것: 나무 꼭대기, 처마, 아치.
- **충돌** — 필요한 곳에서 타일 자체의 통과 가능 여부를 덮어쓰는 행 레이어: 절벽 가장자리의 보이지 않는 벽, 울타리의 빈틈.
- **타일셋** — 타일 아틀라스와 타일 속성(막혀 있는지, 지형, 물건).
- **Spawn** — 새로 도착한 사람이 나타나는 위치. **Zoom**. 실내용 선택 **Ambient** 색(없으면 시간대가 맵을 비춥니다), 그리고 **Atmosphere**(`woodland`은 낙엽, 반딧불, 물결을 추가).
- **Encounters** — 랜덤 전투: 평균 `Steps` 걸음마다 한 번, `Groups` 중 하나와.
```json
"Encounters": { "Steps": 48, "Groups": ["rpg_slime", "rpg_slime,rpg_slime"] }
```
## 작성자용: 이벤트
이벤트는 어느 모드의 `map_events/<맵 id>/*.json`에나 있습니다. 이벤트는 **모습**과 **효과**를 따로 고릅니다.
- 모습: 캐릭터 `Sprite`, 아틀라스의 `Tile` 한 장, 땅에 놓인 아이템 `Icon`, 또는 없음(보이지 않는 트리거).
- 효과: 이 맵이나 다른 맵의 칸으로 가는 `Teleport`, 또는 `Scenario`와 선택적인 인라인 `Commands` — `action rpg.battle`, 플래그, 퀘스트를 포함한 시나리오 언어 전부.
- `Trigger`: `Action`(마주 본 채 E/F) 또는 `Touch`(밟기).
- `Solid`: 길을 막는지(그려지는 이벤트는 기본적으로 막습니다).
- `Condition`: 조건이 맞지 않으면 이벤트를 숨깁니다.
- `Pages`: 각자 조건을 가진 대체 모습과 효과. 조건이 맞는 마지막 페이지가 사용됩니다.
- `Route`: 자율 이동. `{"Steps": ["left", "wait", "right"], "Every": 0.8}` 같은 형태로 `up`/`down`/`left`/`right`, `random`, `toward`/`away`(플레이어 쪽으로/반대로), `wait`, `face_…` 사용.
- `Light`: 이벤트 주위의 빛. `{"Radius": 3, "Color": "#ffd8a0"}`. 저녁과 밤에 보입니다.
**다른 모드의 맵에 추가하거나 바꾸기.** 이벤트 파일은 로드 순서대로 합쳐집니다. 새 `Id`는 그 맵에 이벤트를 추가하고, 소유자에게 의존하는 모드가 같은 `Id`를 쓰면 대체합니다. RPG Plus가 데모의 장로에게 새 대화를 주는 방식이 바로 이것입니다.
## 시나리오 액션
```scenario
action rpg.battle enemies=rpg_wolf,rpg_slime win_flag=rpg_wolf_dead
action rpg.teleport map=rpg_forest x=1 y=8 dir=right
```
- `rpg.battle`은 게임의 전투 코어로 전투를 시작하고 같은 칸으로 돌아옵니다. 승리하면 `win_flag`가 1로 설정되어, 그 플래그를 조건으로 검사하는 맵의 몬스터는 사라집니다. 이 액션 뒤에는 시나리오를 끝내세요.
- `rpg.teleport`는 플레이어를 이 맵이나 다른 맵의 칸으로 옮깁니다.
## 게임 설정
- **외형**(`rpg.player_charset`) — 맵 위 주인공 스프라이트. 게임의 캐릭터셋에서 고릅니다.
- **맵 투영**(`tile.renderer`) — 탑다운 또는 아이소메트릭. Tile Rendering 참조.
## 문제가 생겼을 때
1. **인물이나 상자가 반응하지 않는다.** 마주 보고 서서 E 또는 F를 누르세요. `Touch` 이벤트는 밟았을 때만 반응합니다.
2. **몬스터나 상자가 돌아온다.** 그 `Condition`은 시나리오나 `win_flag`가 설정하는 플래그를 검사해야 합니다.
3. **비어 보이는 곳을 걸을 수 없다.** 그 칸은 막힌 타일이나 맵의 충돌 레이어가 막고 있습니다.
4. **전투 배경이 없다.** `scenes/<map>.json`의 맵 씬에 `defaultBackground`가 필요합니다.
+95
View File
@@ -0,0 +1,95 @@
# RPG World — ходите по тайловой карте, говорите, открывайте, сражайтесь
RPG World превращает игру в RPG на тайловых картах в духе классических двухмерных ролевых игр: вы ходите по карте из клеток, разговариваете с людьми, открываете сундуки, проходите через двери, сражаетесь с монстрами — а после боя возвращаетесь на то же место. Карта при этом остаётся обычной сценой игры, поэтому диалоговое окно, сценарии, сохранения, музыка и время суток работают на ней так же, как в визуальной новелле.
На этом движке построены деревня, лес и пустыня **RPG Plus**. Сами карты и их обитатели лежат в контентных модах вроде RPG Demo; этот мод отвечает за правила.
![Исследование деревни в RPG Plus: название карты слева сверху, панель инструментов справа сверху, подсказка управления слева снизу.](assets/village.jpg)
## Как играть на карте
- **Ходьба** — WASD или стрелки; с зажатым **Shift** герой бежит.
- **Действие** — **E** или **F**: заговорить с тем, кто перед вами, открыть сундук, прочитать табличку.
- **Шагните** на дверной проём или за край карты, чтобы попасть на следующую карту.
- **Случайные бои** могут начинаться прямо на ходу в некоторых местах — например, в лесу.
- После боя вы возвращаетесь на ту же клетку той же карты.
- Игра сохраняет, где вы стоите; загрузка возвращает вас ровно туда же.
Клетку, с которой можно взаимодействовать, обводит рамка, а подсказка слева снизу меняется на **E / F · Взаимодействовать**.
## Пример: сундук, который остаётся открытым
Сундук в доме старейшины — это два события на одной клетке. Закрытый показывается, пока не установлен сюжетный флаг `rpg_house_chest`; его сценарий выдаёт три монеты и ставит флаг. С этого момента вместо закрытого сундука показывается открытый.
![До: герой рядом с закрытым сундуком в доме старейшины в полдень.](assets/chest-before.jpg)
![Текст сундука: старые носки, записка «Не трогай» и три монеты под ними.](assets/chest-text.jpg)
![После: на той же клетке теперь открытый сундук в рамке маркера взаимодействия; подсказка слева снизу гласит «E / F · Взаимодействовать».](assets/chest-after.jpg)
```json
{ "Id": "chest", "X": 9, "Y": 7, "Tile": 14,
"Scenario": "rpg_demo/events/house_chest",
"Condition": "rpg_house_chest != 1" },
{ "Id": "chest_open", "X": 9, "Y": 7, "Tile": 15,
"Scenario": "rpg_demo/events/chest_empty",
"Condition": "rpg_house_chest == 1" }
```
```scenario
ptext "В сундуке — старые носки и записка: «Не трогай». Поздно. Под носками — три монеты." key=rpg_demo/chest/house
action item.add id=money/coin count=3
flag rpg_house_chest 1
end
```
## Авторам: карты
Карта — это JSON-файл в папке `maps/` мода, плюс сцена с тем же именем в `scenes/`: она задаёт фон для боёв и фоновый звук карты.
- **Три рисуемых слоя**, каждый — список строк с номерами тайлов (`.` — пусто): `Back` — земля, полы, вода; `Main` — объекты уровня персонажей: стены, стволы, заборы; `Front` — рисуется поверх персонажей: кроны деревьев, свесы крыш, арки.
- **Коллизии** — слой строк, который там, где нужно, переопределяет проходимость самих тайлов: невидимая стена у края обрыва или проход в живой изгороди.
- **Тайлсет** — атлас тайлов и свойства его тайлов (проходимость, поверхности, объекты).
- **Spawn** — где появляется только что прибывший герой; **Zoom**; необязательный цвет **Ambient** для интерьеров (иначе карту освещает время суток) и **Atmosphere** (`woodland` добавляет листья, светлячков и рябь на воде).
- **Encounters** — случайные бои: в среднем один за каждые `Steps` шагов против одной из групп `Groups`.
```json
"Encounters": { "Steps": 48, "Groups": ["rpg_slime", "rpg_slime,rpg_slime"] }
```
## Авторам: события
События лежат в `map_events/<id карты>/*.json` любого мода. У события независимо друг от друга выбираются **внешний вид** и **эффект**:
- вид: спрайт персонажа `Sprite`, один тайл из атласа `Tile`, иконка предмета `Icon`, лежащего на земле, или ничего (невидимый триггер);
- эффект: `Teleport` в клетку этой или другой карты либо `Scenario` с необязательными командами `Commands` прямо в событии — весь язык сценариев, включая `action rpg.battle`, флаги и задания;
- `Trigger`: `Action` (E/F, когда вы стоите к нему лицом) или `Touch` (наступить на событие);
- `Solid`: блокирует ли путь (нарисованные события по умолчанию блокируют);
- `Condition`: скрыть событие, пока условие не выполняется;
- `Pages`: альтернативные вид и эффект, у каждого своё условие; используется последняя страница с выполненным условием;
- `Route`: самостоятельное движение вроде `{"Steps": ["left", "wait", "right"], "Every": 0.8}` с направлениями `up`/`down`/`left`/`right`, режимами `random`, `toward`/`away` (к игроку и от него), а также `wait` и `face_…`;
- `Light`: свечение вокруг события, `{"Radius": 3, "Color": "#ffd8a0"}`; видно в сумерках и ночью.
**Дополняйте и меняйте карты чужих модов.** Файлы событий сливаются в порядке загрузки: новый `Id` добавляет событие на карту, а тот же `Id` от мода, который зависит от владельца карты, заменяет его. Именно так RPG Plus даёт старейшине из демо новые диалоги.
## Действия сценариев
```scenario
action rpg.battle enemies=rpg_wolf,rpg_slime win_flag=rpg_wolf_dead
action rpg.teleport map=rpg_forest x=1 y=8 dir=right
```
- `rpg.battle` запускает бой боевым ядром игры и возвращает героя на ту же клетку; при победе `win_flag` получает значение 1 — и монстр на карте, чьё условие проверяет этот флаг, исчезает. После этого действия сценарий нужно завершать.
- `rpg.teleport` переносит игрока в клетку этой или другой карты.
## Настройки игры
- **Внешний вид** (`rpg.player_charset`) — спрайт героя на картах, выбирается из чарсетов игры.
- **Проекция карты** (`tile.renderer`) — вид сверху или изометрия; см. Tile Rendering.
## Если что-то пошло не так
1. **Персонаж или сундук не реагирует.** Встаньте к нему лицом и нажмите E или F; событие с `Touch` срабатывает, только если на него наступить.
2. **Монстр или сундук возвращается.** Его `Condition` должен проверять тот флаг, который выставляет его сценарий или `win_flag`.
3. **Не пройти туда, где вроде бы открыто.** Клетку блокирует непроходимый тайл или слой коллизий карты.
4. **Нет фона для боя.** Сцене карты в `scenes/<map>.json` нужен `defaultBackground`.
+95
View File
@@ -0,0 +1,95 @@
# RPG World — đi lại trên bản đồ ô, trò chuyện, mở rương, chiến đấu
RPG World biến trò chơi thành RPG bản đồ ô theo tinh thần các game nhập vai 2D cổ điển: bạn đi trên lưới ô bằng bàn phím, nói chuyện với mọi người, mở rương, bước qua cửa và chiến đấu với quái vật, rồi trở về đúng chỗ cũ. Bản đồ vẫn là một cảnh bình thường của trò chơi, nên hộp hội thoại, kịch bản, lưu game, nhạc và thời gian trong ngày đều hoạt động trên bản đồ như trong tiểu thuyết thị giác.
Chính nó vận hành làng, rừng và sa mạc của **RPG Plus**. Bản đồ và nhân vật đến từ các mod nội dung như RPG Demo; còn mod này cung cấp luật chơi.
![Đang khám phá làng trong RPG Plus: tên bản đồ ở trên trái, thanh công cụ ở trên phải, gợi ý điều khiển ở dưới trái.](assets/village.jpg)
## Chơi trên bản đồ như thế nào
- **Đi lại** bằng WASD hoặc phím mũi tên; giữ **Shift** để chạy.
- **Tương tác** bằng **E** hoặc **F**: nói chuyện với người đang đối mặt, mở rương, đọc biển hiệu.
- **Bước lên** cửa hoặc rìa bản đồ để sang bản đồ kế tiếp.
- Ở một số nơi, ví dụ khu rừng, **trận chiến ngẫu nhiên** có thể nổ ra khi bạn đi lại.
- Sau trận chiến bạn trở về đúng ô cũ của bản đồ cũ.
- Trò chơi lưu vị trí bạn đang đứng; tải lại là về đúng đó.
Ô có thể tương tác được viền khung, và gợi ý ở dưới trái đổi thành **E / F · Interact**.
## Ví dụ: chiếc rương vẫn mở
Chiếc rương trong nhà trưởng lão là hai sự kiện trên cùng một ô. Rương đóng hiện ra khi cờ cốt truyện `rpg_house_chest` chưa được đặt; kịch bản của nó trao ba đồng xu và đặt cờ. Từ đó thay vào đó là chiếc rương mở.
![Trước: nhân vật chính đứng cạnh rương đóng trong nhà trưởng lão lúc buổi trưa.](assets/chest-before.jpg)
![Dòng chữ của rương: tất cũ, mẩu giấy "Đừng động vào", và ba đồng xu bên dưới.](assets/chest-text.jpg)
![Sau: ô cũ giờ hiển thị rương mở, được viền bởi dấu tương tác; gợi ý dưới trái hiện "E / F · Interact".](assets/chest-after.jpg)
```json
{ "Id": "chest", "X": 9, "Y": 7, "Tile": 14,
"Scenario": "rpg_demo/events/house_chest",
"Condition": "rpg_house_chest != 1" },
{ "Id": "chest_open", "X": 9, "Y": 7, "Tile": 15,
"Scenario": "rpg_demo/events/chest_empty",
"Condition": "rpg_house_chest == 1" }
```
```scenario
ptext "Trong rương: tất cũ và một mẩu giấy ghi "Đừng động vào". Muộn rồi. Dưới đống tất: ba đồng xu." key=rpg_demo/chest/house
action item.add id=money/coin count=3
flag rpg_house_chest 1
end
```
## Dành cho tác giả: bản đồ
Bản đồ là một tệp JSON trong thư mục `maps/` của mod, kèm một cảnh cùng tên trong `scenes/` làm nền chiến đấu và âm nền của bản đồ.
- **Ba lớp vẽ**, mỗi lớp là danh sách các hàng số ô (`.` là trống): `Back` — mặt đất, sàn, nước; `Main` — vật thể ngang tầm nhân vật: tường, thân cây, hàng rào; `Front` — vẽ đè lên nhân vật: tán cây, mái hiên, vòm cửa.
- **Va chạm** — lớp theo hàng, ghi đè khả năng đi qua của ô khi cần: bức tường vô hình ở mép vách hay chỗ hở trong hàng rào cây.
- **Tileset** — atlas ô và thuộc tính từng ô (có đặc hay không, nền, vật thể).
- **Spawn** — người mới xuất hiện ở đâu; **Zoom**; màu **Ambient** tùy chọn cho nội thất (nếu không, thời gian trong ngày sẽ chiếu sáng bản đồ) và **Atmosphere** (`woodland` thêm lá, đom đóm và gợn nước).
- **Encounters** — chiến đấu ngẫu nhiên: trung bình một lần mỗi `Steps` bước, gặp một trong các `Groups`.
```json
"Encounters": { "Steps": 48, "Groups": ["rpg_slime", "rpg_slime,rpg_slime"] }
```
## Dành cho tác giả: sự kiện
Sự kiện nằm trong `map_events/<id bản đồ>/*.json` của bất kỳ mod nào. Một sự kiện có **diện mạo** và **tác dụng** được chọn riêng biệt:
- diện mạo: `Sprite` nhân vật, một ô `Tile` từ atlas, `Icon` vật phẩm nằm trên đất, hoặc không gì cả (bộ kích hoạt vô hình);
- tác dụng: `Teleport` tới một ô của bản đồ này hoặc bản đồ khác, hoặc `Scenario` kèm `Commands` viết ngay tại chỗ (tùy chọn) — ngôn ngữ kịch bản đầy đủ, kể cả `action rpg.battle`, cờ và nhiệm vụ;
- `Trigger`: `Action` (E/F khi đang đối mặt) hoặc `Touch` (bước lên);
- `Solid`: có chặn đường hay không (mặc định, sự kiện được vẽ ra sẽ chặn);
- `Condition`: ẩn sự kiện khi điều kiện không thỏa;
- `Pages`: các diện mạo và tác dụng thay thế, mỗi cái một điều kiện; dùng trang cuối cùng có điều kiện thỏa;
- `Route`: di chuyển tự động như `{"Steps": ["left", "wait", "right"], "Every": 0.8}`, với `up`/`down`/`left`/`right`, `random`, `toward`/`away` (về phía hoặc xa khỏi người chơi), `wait` và `face_…`;
- `Light`: quầng sáng quanh sự kiện, `{"Radius": 3, "Color": "#ffd8a0"}`, nhìn thấy lúc chạng vạng và ban đêm.
**Thêm vào hoặc thay đổi bản đồ của mod khác.** Các tệp sự kiện được gộp theo thứ tự nạp: `Id` mới thêm sự kiện vào bản đồ, còn cùng `Id` từ một mod phụ thuộc vào chủ nhân sẽ thay thế nó. RPG Plus đã cho trưởng lão bản demo những hội thoại mới nhờ cách này.
## Hành động kịch bản
```scenario
action rpg.battle enemies=rpg_wolf,rpg_slime win_flag=rpg_wolf_dead
action rpg.teleport map=rpg_forest x=1 y=8 dir=right
```
- `rpg.battle` mở một trận chiến bằng lõi chiến đấu của trò chơi rồi trở về đúng ô cũ; khi thắng, `win_flag` được đặt thành 1, nhờ vậy quái vật trên bản đồ mà điều kiện của nó kiểm tra cờ này sẽ biến mất. Hãy kết thúc kịch bản sau hành động này.
- `rpg.teleport` đưa người chơi tới một ô trên bản đồ này hoặc bản đồ khác.
## Cài đặt trò chơi
- **Diện mạo** (`rpg.player_charset`) — sprite của nhân vật chính trên bản đồ, chọn từ các charset trong trò chơi.
- **Phép chiếu bản đồ** (`tile.renderer`) — nhìn từ trên hoặc đẳng cự; xem Tile Rendering.
## Khi có trục trặc
1. **Nhân vật hay rương không phản ứng.** Đối mặt và nhấn E hoặc F; sự kiện `Touch` chỉ phản ứng khi bạn bước lên.
2. **Quái vật hay rương quay lại.** `Condition` của nó phải kiểm tra đúng cờ mà kịch bản hoặc `win_flag` của nó đặt.
3. **Chỗ trông có vẻ trống lại không đi được.** Ô đó bị ô đặc hoặc lớp va chạm của bản đồ chặn.
4. **Không có nền trận chiến.** Cảnh của bản đồ trong `scenes/<map>.json` cần `defaultBackground`.
+95
View File
@@ -0,0 +1,95 @@
# RPG World — 在图块地图上行走、交谈、开启与战斗
RPG World 把游戏变成经典 2D 角色扮演风格的图块地图 RPG:用键盘在网格地图上行走,与人交谈,打开宝箱,穿过房门,与怪物战斗——打完再回到原地。地图本身就是游戏的普通场景,所以对话框、剧本、存档、音乐和昼夜变化在地图上的表现与视觉小说里完全一样。
**RPG Plus** 的村庄、森林和沙漠都由它驱动。地图和人物本身来自 RPG Demo 之类的内容模组;这个模组提供的是规则。
![在 RPG Plus 中探索村庄:左上角是地图名,右上角是工具栏,左下角是操作提示。](assets/village.jpg)
## 在地图上怎么玩
- **行走**用 WASD 或方向键;按住 **Shift** 奔跑。
- **互动**用 **E** 或 **F**:与面前的人交谈、打开宝箱、阅读告示牌。
- **走上**门口或地图边缘即可前往下一张地图。
- 在某些地方(例如森林)行走时可能触发**随机战斗**。
- 战斗结束后,你会回到原地图的原格子。
- 游戏会保存你站立的位置;读档后回到原地。
可以互动的格子会被框起来,左下角的提示随之变为 **E / F · Interact**。
## 示例:保持开启的宝箱
长者之家的宝箱由同一格子上的两个事件组成。剧情旗标 `rpg_house_chest` 未设置时显示关闭的宝箱;它的剧本会给出三枚硬币并设置旗标。此后改而显示打开的宝箱。
![之前:正午,长者之家中主角站在关闭的宝箱旁。](assets/chest-before.jpg)
![宝箱的文字:旧袜子、一张写着"别碰"的纸条,以及压在下面的三枚硬币。](assets/chest-text.jpg)
![之后:同一格子现在显示打开的宝箱,并被互动标记框住;左下角提示为"E / F · Interact"。](assets/chest-after.jpg)
```json
{ "Id": "chest", "X": 9, "Y": 7, "Tile": 14,
"Scenario": "rpg_demo/events/house_chest",
"Condition": "rpg_house_chest != 1" },
{ "Id": "chest_open", "X": 9, "Y": 7, "Tile": 15,
"Scenario": "rpg_demo/events/chest_empty",
"Condition": "rpg_house_chest == 1" }
```
```scenario
ptext "箱子里:旧袜子和一张写着"别碰"的纸条。太迟了。袜子下面有三枚硬币。" key=rpg_demo/chest/house
action item.add id=money/coin count=3
flag rpg_house_chest 1
end
```
## 给作者:地图
地图是模组 `maps/` 文件夹里的一个 JSON 文件,另外还要在 `scenes/` 里放一个同名场景,用于战斗背景和地图的环境音。
- **三个绘制图层**,各是一份按行排列的图块编号列表(`.` 表示空):`Back`——地面、地板、水;`Main`——与角色同层的物件:墙、树干、栅栏;`Front`——绘制在角色之上:树冠、屋檐、拱门。
- **碰撞**——一层按行记录的数据,在需要的地方覆盖图块自身的通行性:悬崖边的隐形墙,或树篱上的缺口。
- **图块集(tileset)**——图块图集以及各图块的属性(是否实心、地表、物件)。
- **Spawn**——新到来者出现的位置;**Zoom**;可选的 **Ambient** 颜色,用于室内(否则地图由昼夜光照);以及 **Atmosphere**(`woodland` 会添加落叶、萤火虫和水面涟漪)。
- **Encounters**——随机战斗:平均每走 `Steps` 步遇到一次,对手是 `Groups` 中的一组。
```json
"Encounters": { "Steps": 48, "Groups": ["rpg_slime", "rpg_slime,rpg_slime"] }
```
## 给作者:事件
事件存放在任意模组的 `map_events/<地图 id>/*.json` 中。每个事件都有相互独立的**外观**和**效果**:
- 外观:角色 `Sprite`、图块集里的单个 `Tile`、放在地上的物品 `Icon`,或者什么都不画(隐形触发器);
- 效果:`Teleport` 到本地图或另一张地图的某格,或者 `Scenario` 加可选的内联 `Commands`——完整的剧本语言,包括 `action rpg.battle`、旗标和任务;
- `Trigger`:`Action`(面向它按 E/F)或 `Touch`(踩上去);
- `Solid`:是否挡路(画出来的事件默认挡路);
- `Condition`:条件不成立时隐藏事件;
- `Pages`:备选的外观和效果,各自带条件;使用最后一条条件成立的页面;
- `Route`:自主移动,例如 `{"Steps": ["left", "wait", "right"], "Every": 0.8}`,可用 `up`/`down`/`left`/`right`、`random`、`toward`/`away`(朝向或远离玩家)、`wait` 和 `face_…`;
- `Light`:事件周围的光晕,`{"Radius": 3, "Color": "#ffd8a0"}`,黄昏和夜晚可见。
**增补或修改其他模组的地图。** 事件文件按加载顺序合并:新的 `Id` 向地图添加事件;依赖地图归属模组的模组若使用相同的 `Id`,则替换该事件。RPG Plus 就是这样给演示版的年长者加上新对话的。
## 剧本动作
```scenario
action rpg.battle enemies=rpg_wolf,rpg_slime win_flag=rpg_wolf_dead
action rpg.teleport map=rpg_forest x=1 y=8 dir=right
```
- `rpg.battle` 用游戏的战斗核心开启一场战斗,并回到同一格;胜利时 `win_flag` 被置为 1,于是地图上条件检查该旗标的怪物就会消失。这个动作之后应结束剧本。
- `rpg.teleport` 把玩家移动到本地图或另一张地图的某格。
## 游戏设置
- **外观**(`rpg.player_charset`)——主角在地图上的精灵,从游戏的字符图(charset)中选择。
- **地图投影**(`tile.renderer`)——俯视或等距;参见 Tile Rendering。
## 如果遇到问题
1. **人物或宝箱没有反应。** 面对它按 E 或 F;`Touch` 事件只有踩上去才会触发。
2. **怪物或宝箱又出现了。** 它的 `Condition` 必须检查它的剧本或 `win_flag` 所设置的旗标。
3. **看起来能走的地方走不过去。** 那个格子被实心图块或地图的碰撞层挡住了。
4. **战斗没有背景。** 地图在 `scenes/<map>.json` 中的场景需要 `defaultBackground`。