Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc56c64b77 | ||
|
|
d7250b26b2 | ||
|
|
c975b5ae86 |
No files matched your search
+21
-7
@@ -6,9 +6,9 @@ It opens from the tool box (the hammer on the toolbar) as **Characters**.
|
||||
|
||||
## An edit and its result in the game
|
||||
|
||||
In RPG Plus, the hero of the village is the character `rpg_hero` of the mod `rpg_demo_game`. Choose that mod at the top, pick **Hero**, type a new English name and press **Save** (Ctrl+S):
|
||||
In RPG Plus, the hero of the village is the character `rpg_hero` of the mod `rpg_plus_game`. Choose that mod at the top, pick **Hero**, type a new English name and press **Save** (Ctrl+S):
|
||||
|
||||

|
||||

|
||||
|
||||
Only the English line of the mod's `locale/en.properties` changed. The party member on the character panel right after:
|
||||
|
||||
@@ -21,21 +21,35 @@ The panel shows HP 42 and ATK 12 while the file says 24 and 6: in RPG Plus the h
|
||||
- **Id** — the character's id; scenarios, parties, battles and maps find it by this id.
|
||||
- **Name** — the translation key and a line per language of the mod.
|
||||
- **Portrait** — the picture on cards and panels; **…** opens a grid to pick one.
|
||||
- **Charset (RPG)** — the walking sprite on RPG maps (3 frames × 4 facings). The RPG Map Editor offers characters with their charset for placing.
|
||||
- **Level**, **Health**, **Attack**, **Defence**, **Action points**, **Experience** — the battle numbers of the character.
|
||||
- **Charset (RPG)** — the walking sprite on RPG maps (3 frames × 4 facings).
|
||||
- **Level**, **Health**, **Attack**, **Defence**, **Action points**, **Experience** — the battle numbers of the character. When the character has `Stats` (from the Stats Engine), **Health**, **Attack** and **Defence** are read-only: the stats compute them, and the form shows the computed values under the fields (see the party block below).
|
||||
- **Recruit chance** — 0 to 100: the chance to capture the character after beating it (see Recruiting).
|
||||
- **Behaviour** and **Actions** — how the character fights and which battle actions it has.
|
||||
- **Loot** — what drops when the character is defeated as an enemy: a list of rows, each with an item (a picker of the items the game knows), a minimum and a maximum count and a chance from 0 to 100.
|
||||
- **Fields of other mods** — fields other mods describe for characters in their schemas (for example Stats Engine's class, stats and traits) appear in their own section.
|
||||
- **Id** of a saved character is read-only; **Rename…** under it changes the id and the references to it (see below).
|
||||
- **Other fields** — the rest of the character's JSON, edited as JSON and kept as it is.
|
||||
|
||||
The toolbar: **New** (Ctrl+N), **Copy** (Ctrl+D), **Delete**, **Undo**/**Redo** (Ctrl+Z / Ctrl+Y), **Save** — only changed files are written; texts go into the mod's locale files.
|
||||
|
||||
## Which characters can be edited
|
||||
## Renaming an id
|
||||
|
||||
The list holds the characters in the selected mod's own files; only mods installed as folders are offered. Characters of other mods are not in the list and their files are never written. To change one of them, ship the same id in your own mod with a dependency on the owner, or add fields with a patch.
|
||||
**Rename…** under the Id of a saved character asks for the new id and lists every file that names the character before anything is written: the character's own file, the scenarios that give it to a party or start a battle with it, the placements and maps that place it. Files of other mods that name it are only listed, and they are not changed. **Rename** saves your pending edits first; **Undo rename** in the toolbar puts every changed file back exactly as it was. Ids take letters, digits, `_`, `-` and `/` between their parts, and must be free in every mod.
|
||||
|
||||
## The party block
|
||||
|
||||
Below the fields, the party block shows two things:
|
||||
|
||||
- **Party leader** — the character whose sheet the player walks with on RPG maps. The leader is the character the game's `stats.player` names; without one, the first character of the battle party. The block says *Party leader* or *Not the party leader* for the open character. Choosing a new leader is not a button yet: it is a setting of the collection, changed through the mod manager.
|
||||
- **Computed battle numbers** — when the character has `Stats`, every stat with its value and its battle number. The hint says that health, attack and defence come from the stats, so you edit the stats, not these fields. Without `Stats` the block says so, and the battle numbers are the fields above.
|
||||
- **Joins the party when talked to** — tick it to write the join scenario `scenarios/<your mod>/party/<id>.scenario`: it sets the flag `<id>_joined` to 1 and adds the character to the party (`action party.add`). Unticking deletes the file at once. The leader never joins (the box is disabled). If the character's actor object already has a dialog (its **Interaction** opens a scenario or has its own lines), the join comes after that dialog: the dialog plays, then the character joins, and the dialog is not replaced. The map editor writes this when the character is chosen in its **Characters** tab. To make the character a companion on a map, place it from the **Characters** tab of the RPG Map Editor: talking to the placed actor joins it, the actor leaves its cell and the companion walks behind the hero.
|
||||
|
||||
## Characters of other mods
|
||||
|
||||
The list shows the characters of the chosen mod. Tick **Entries of other mods** to add the characters of its dependencies, marked `↗ owner`. Editing one writes a patch in your mod (`patches/character/<your mod>.json`) with only the values you changed; the owner's file stays byte for byte the same. **Reset to inherited** removes the patch, and **↺** next to a field removes your value of that field. Only mods installed as folders can be written to.
|
||||
|
||||
## If something goes wrong
|
||||
|
||||
1. **Changed health or attack has no effect.** The game computes the numbers from stats, as RPG Plus does for its party.
|
||||
2. **The character is missing from the RPG Map Editor's Characters tab.** The tab lists characters with combat stats; any sprite can still be placed from the Appearance tab.
|
||||
2. **The character is not in the RPG Map Editor's palette.** The palette's **Characters** tab lists the characters that have a walking sheet (**Charset**); a character without one cannot be placed. The **Actors** tab lists the actor objects of `rpg_object`, not the game's characters.
|
||||
3. **The mod list is empty.** Packed mods cannot be edited.
|
||||
+14
-6
@@ -6,9 +6,9 @@ Se abre desde la caja de herramientas (el martillo de la barra) como **Personaje
|
||||
|
||||
## Una edición y su resultado en el juego
|
||||
|
||||
En RPG Plus, el héroe de la aldea es el personaje `rpg_hero` del mod `rpg_demo_game`. Elige ese mod arriba, selecciona **Héroe**, escribe un nombre nuevo en inglés y pulsa **Guardar** (Ctrl+S):
|
||||
En RPG Plus, el héroe de la aldea es el personaje `rpg_hero` del mod `rpg_plus_game`. Elige ese mod arriba, selecciona **Héroe**, escribe un nombre nuevo en inglés y pulsa **Guardar** (Ctrl+S):
|
||||
|
||||

|
||||

|
||||
|
||||
Solo cambió la línea en inglés del `locale/en.properties` del mod. El miembro del grupo en el panel de personajes justo después:
|
||||
|
||||
@@ -21,7 +21,7 @@ El panel muestra HP 42 y ATK 12 aunque el archivo dice 24 y 6: en RPG Plus la cl
|
||||
- **Id** — el id del personaje; por él lo encuentran escenarios, grupos, combates y mapas.
|
||||
- **Nombre** — la clave de traducción y una línea por idioma del mod.
|
||||
- **Retrato** — la imagen en tarjetas y paneles; **…** abre una cuadrícula para elegir una.
|
||||
- **Charset (RPG)** — el sprite de paseo en los mapas RPG (3 fotogramas × 4 orientaciones). El editor de mapas RPG ofrece los personajes con su charset para colocarlos.
|
||||
- **Charset (RPG)** — el sprite de paseo en los mapas RPG (3 fotogramas × 4 orientaciones).
|
||||
- **Nivel**, **Salud**, **Ataque**, **Defensa**, **Puntos de acción**, **Experiencia** — las cifras de combate del personaje.
|
||||
- **Probabilidad de reclutar** — de 0 a 100: la probabilidad de capturar al personaje tras vencerlo (ver Recruiting).
|
||||
- **Comportamiento** y **Acciones** — cómo pelea el personaje y qué acciones de combate tiene.
|
||||
@@ -30,12 +30,20 @@ El panel muestra HP 42 y ATK 12 aunque el archivo dice 24 y 6: en RPG Plus la cl
|
||||
|
||||
La barra: **Nueva** (Ctrl+N), **Copia** (Ctrl+D), **Borrar**, **Deshacer**/**Rehacer** (Ctrl+Z / Ctrl+Y), **Guardar** — solo se escriben los archivos cambiados; los textos van a los archivos de localización del mod.
|
||||
|
||||
## Qué personajes se pueden editar
|
||||
## Personajes de otros mods
|
||||
|
||||
La lista contiene los personajes de los archivos del mod seleccionado; solo se ofrecen los mods instalados como carpetas. Los personajes de otros mods no están en la lista y sus archivos nunca se escriben. Para cambiar uno de ellos, incluye el mismo id en tu propio mod con una dependencia del dueño, o añade campos con un parche.
|
||||
La lista muestra los personajes del mod elegido. Marque **Entries of other mods** para añadir los personajes de sus dependencias, marcados `↗ dueño`. Editar uno escribe un parche en su mod (`patches/character/<su mod>.json`) solo con los valores que cambió; el archivo del dueño queda idéntico byte a byte. **Reset to inherited** quita el parche, y **↺** junto a un campo quita su valor. Solo se puede escribir en mods instalados como carpeta.
|
||||
|
||||
## El bloque del grupo
|
||||
|
||||
Bajo los campos, el bloque del grupo muestra dos cosas:
|
||||
|
||||
- **Líder del grupo** — el personaje cuya ficha usa el jugador al caminar por los mapas RPG. El líder es el que nombra `stats.player` del juego; si no hay ninguno, el primer personaje del grupo de combate. El bloque dice *Party leader* o *Not the party leader* para el personaje abierto. Todavía no hay botón para elegir otro líder: es un ajuste de la colección y se cambia desde el gestor de mods.
|
||||
- **Cifras de combate calculadas** — si el personaje tiene `Stats`, cada estadística con su valor y su cifra de combate. La pista indica que la salud, el ataque y la defensa vienen de las estadísticas, así que se editan estas y no los campos. Con `Stats`, **Health**, **Attack** y **Defence** son de solo lectura. Sin `Stats`, el bloque lo dice y las cifras de combate son los campos de arriba.
|
||||
- **Se une al grupo al hablar con él** — márquelo para escribir el escenario de unión `scenarios/<su mod>/party/<id>.scenario`: pone el flag `<id>_joined` a 1 y añade el personaje al grupo (`action party.add`). Quitar la marca borra el archivo al instante. El líder nunca se une (la casilla está desactivada). Para que el personaje sea un compañero en el mapa, colóquelo desde la pestaña **Personajes** del editor de mapas RPG: hablar con el actor colocado lo une, el actor deja su casilla y el compañero camina detrás del héroe.
|
||||
|
||||
## Si algo sale mal
|
||||
|
||||
1. **Cambiar salud o ataque no tiene efecto.** El juego calcula las cifras a partir de los atributos, como hace RPG Plus con su grupo.
|
||||
2. **El personaje no está en la pestaña Personajes del editor de mapas RPG.** La pestaña lista personajes con estadísticas de combate; cualquier sprite se puede colocar desde la pestaña Appearance.
|
||||
2. **El personaje no está en la paleta del editor de mapas RPG.** La pestaña **Personajes** solo muestra los personajes con hoja de movimiento (**Charset**); sin ella no se puede colocar. La pestaña **Actores** muestra los objetos `rpg_object`, no los personajes del juego.
|
||||
3. **La lista de mods está vacía.** Los mods empaquetados no se pueden editar.
|
||||
+14
-6
@@ -6,9 +6,9 @@ Characters Editor は、ゲームの実行中に MOD のキャラクターを編
|
||||
|
||||
## 編集と、ゲームの中での結果
|
||||
|
||||
RPG Plus では、村の英雄は MOD `rpg_demo_game` のキャラクター `rpg_hero` です。上でその MOD を選び、**勇者**を選び、新しい英語名を入力して**保存**(Ctrl+S)を押します:
|
||||
RPG Plus では、村の英雄は MOD `rpg_plus_game` のキャラクター `rpg_hero` です。上でその MOD を選び、**勇者**を選び、新しい英語名を入力して**保存**(Ctrl+S)を押します:
|
||||
|
||||

|
||||

|
||||
|
||||
変わったのは MOD の `locale/en.properties` の英語の行だけです。直後のキャラクターパネルのパーティメンバー:
|
||||
|
||||
@@ -21,7 +21,7 @@ RPG Plus では、村の英雄は MOD `rpg_demo_game` のキャラクター `rpg
|
||||
- **Id** — キャラクターの id。シナリオ、パーティ、バトル、マップがこれで見つけます。
|
||||
- **名前** — 翻訳キーと、MOD の言語ごとの行。
|
||||
- **肖像** — カードやパネルの画像。**…** で選ぶためのグリッドが開きます。
|
||||
- **キャラチップ(RPG)** — RPG マップ上の歩行グラフィック(3 コマ × 4 方向)。RPG マップエディターは、配置のときにキャラチップ付きのキャラクターを提示します。
|
||||
- **キャラチップ(RPG)** — RPG マップ上の歩行グラフィック(3 コマ × 4 方向)。
|
||||
- **レベル**、**体力**、**攻撃**、**防御**、**行動ポイント**、**経験値** — キャラクターの戦闘の数値。
|
||||
- **勧誘の確率** — 0〜100: 倒したあとにキャラクターを迎える確率(Recruiting を参照)。
|
||||
- **行動パターン**と**アクション** — キャラクターがどう戦うか、どんなバトルアクションを持つか。
|
||||
@@ -30,12 +30,20 @@ RPG Plus では、村の英雄は MOD `rpg_demo_game` のキャラクター `rpg
|
||||
|
||||
ツールバー: **新規**(Ctrl+N)、**コピー**(Ctrl+D)、**削除**、**元に戻す**/**やり直す**(Ctrl+Z / Ctrl+Y)、**保存** — 変更されたファイルだけが書き込まれ、テキストは MOD のローカライズファイルに入ります。
|
||||
|
||||
## どのキャラクターを編集できるか
|
||||
## 他のモッドのキャラクター
|
||||
|
||||
一覧には、選んだ MOD 自身のファイルにあるキャラクターが入ります。提示されるのは、フォルダーとしてインストールされた MOD だけです。他の MOD のキャラクターは一覧になく、そのファイルが書かれることもありません。変えるには、自分の MOD で同じ id を所有者への依存関係付きで配るか、パッチでフィールドを足します。
|
||||
一覧には選んだモッドのキャラクターが並びます。**Entries of other mods** をオンにすると依存先のキャラクターも加わり、`↗ 所有者` の印が付きます。そのキャラクターを編集すると、自分のモッドに `patches/character/<自分のモッド>.json` というパッチが書かれ、変えた値だけが入ります。所有者のファイルはバイト単位で元のままです。**Reset to inherited** でパッチを外し、項目の横の **↺** でその項目の自分の値を外せます。書き込めるのはフォルダとしてインストールされたモッドだけです。
|
||||
|
||||
## パーティのブロック
|
||||
|
||||
フォームの下のパーティのブロックには二つ表示されます。
|
||||
|
||||
- **パーティのリーダー** — プレイヤーが RPG マップで歩くときに使うシートのキャラクター。リーダーはゲームの `stats.player` が指すキャラクターで、なければ戦闘パーティの先頭です。ブロックには、開いているキャラクターが「Party leader」か「Not the party leader」かが表示されます。リーダーを変えるボタンはまだありません。コレクションの設定で、モッドマネージャーから変更します。
|
||||
- **計算された戦闘の数値** — キャラクターに `Stats` がある場合、各ステータスの値と戦闘の数値を表示します。ヒントには、体力・攻撃・防御はステータスから来るので、この欄ではなくステータスを編集するよう書かれています。`Stats` があるキャラクターでは **Health**、**Attack**、**Defence** は読み取り専用です。`Stats` がなければ、ブロックにその旨が出て、戦闘の数値は上の欄の値になります。
|
||||
- **話しかけると仲間に加わる** — オンにすると加入シナリオ `scenarios/<あなたのMod>/party/<id>.scenario` を書き込みます。フラグ `<id>_joined` を 1 にし、キャラクターを仲間に加えます(`action party.add`)。オフにすると直ちにファイルを削除します。リーダーは加わりません(チェックボックスは無効)。マップで仲間として使うには、RPGマップエディタの「キャラクター」タブで配置します。配置したアクターに話しかけると加わり、アクターは元のマスを離れ、仲間は主人公の後ろについて歩きます。
|
||||
|
||||
## うまくいかないとき
|
||||
|
||||
1. **体力や攻撃を変えても効かない。** ゲームはステータスから数値を計算します。RPG Plus がパーティに対してしているように。
|
||||
2. **キャラクターが RPG マップエディターの「キャラクター」タブにいない。** このタブは戦闘ステータスのあるキャラクターを一覧します。どんなグラフィックでも「Appearance」タブから配置できます。
|
||||
2. **キャラクターがRPGマップエディタのパレットにありません。** 「キャラクター」タブには歩行スプライト(**Charset**)を持つキャラクターだけが並びます。ないと配置できません。「アクター」タブに並ぶのは `rpg_object` のアクターオブジェクトで、ゲームのキャラクターではありません。
|
||||
3. **MOD の一覧が空。** パッケージ済みの MOD は編集できません。
|
||||
+14
-6
@@ -6,9 +6,9 @@ Characters Editor는 게임이 실행되는 동안 모드의 캐릭터를 편집
|
||||
|
||||
## 편집 하나와 게임 속 결과
|
||||
|
||||
RPG Plus에서 마을의 영웅은 모드 `rpg_demo_game`의 캐릭터 `rpg_hero`입니다. 위에서 그 모드를 고르고, **영웅**을 고르고, 새 영어 이름을 입력한 뒤 **저장**(Ctrl+S)을 누릅니다:
|
||||
RPG Plus에서 마을의 영웅은 모드 `rpg_plus_game`의 캐릭터 `rpg_hero`입니다. 위에서 그 모드를 고르고, **영웅**을 고르고, 새 영어 이름을 입력한 뒤 **저장**(Ctrl+S)을 누릅니다:
|
||||
|
||||

|
||||

|
||||
|
||||
바뀐 것은 모드 `locale/en.properties`의 영어 한 줄입니다. 바로 뒤 캐릭터 패널의 파티원:
|
||||
|
||||
@@ -21,7 +21,7 @@ RPG Plus에서 마을의 영웅은 모드 `rpg_demo_game`의 캐릭터 `rpg_hero
|
||||
- **Id** — 캐릭터의 id. 시나리오, 파티, 전투, 맵이 이것으로 찾습니다.
|
||||
- **이름** — 번역 키와 모드의 언어별 줄.
|
||||
- **초상화** — 카드와 패널의 그림. **…**를 누르면 고르는 격자가 열립니다.
|
||||
- **캐릭터 시트 (RPG)** — RPG 맵 위의 걷기 스프라이트(3프레임 × 4방향). RPG 맵 에디터는 배치할 때 캐릭터 시트와 함께 캐릭터를 제안합니다.
|
||||
- **캐릭터 시트 (RPG)** — RPG 맵 위의 걷기 스프라이트(3프레임 × 4방향).
|
||||
- **레벨**, **체력**, **공격**, **방어**, **행동 포인트**, **경험치** — 캐릭터의 전투 수치.
|
||||
- **영입 확률** — 0~100: 쓰러뜨린 뒤 캐릭터를 들일 확률(Recruiting 참고).
|
||||
- **행동 방식**과 **액션** — 캐릭터가 어떻게 싸우는지, 어떤 전투 액션을 가지는지.
|
||||
@@ -30,12 +30,20 @@ RPG Plus에서 마을의 영웅은 모드 `rpg_demo_game`의 캐릭터 `rpg_hero
|
||||
|
||||
도구 모음: **새로 만들기**(Ctrl+N), **복사**(Ctrl+D), **삭제**, **되돌리기**/**다시 실행**(Ctrl+Z / Ctrl+Y), **저장** — 바뀐 파일만 기록되고, 텍스트는 모드의 로컬라이즈 파일로 갑니다.
|
||||
|
||||
## 어떤 캐릭터를 편집할 수 있는가
|
||||
## 다른 모드의 캐릭터
|
||||
|
||||
목록에는 선택한 모드 자신의 파일에 있는 캐릭터가 있습니다. 폴더로 설치된 모드만 제안됩니다. 다른 모드의 캐릭터는 목록에 없고 그 파일은 결코 기록되지 않습니다. 바꾸려면 소유자에 대한 의존성과 함께 같은 id를 자기 모드에 실거나, 패치로 필드를 더하세요.
|
||||
목록에는 고른 모드의 캐릭터가 나옵니다. **Entries of other mods**를 켜면 의존하는 모드의 캐릭터도 `↗ 소유자` 표시와 함께 추가됩니다. 그런 캐릭터를 편집하면 여러분의 모드에 `patches/character/<여러분의 모드>.json` 패치가 기록되며, 바꾼 값만 들어갑니다. 소유자의 파일은 바이트 단위로 그대로 남습니다. **Reset to inherited**는 패치를 지우고, 항목 옆 **↺**는 그 항목에 대한 여러분의 값을 지웁니다. 폴더로 설치된 모드에만 기록할 수 있습니다.
|
||||
|
||||
## 파티 블록
|
||||
|
||||
양식 아래의 파티 블록에는 두 가지가 나옵니다.
|
||||
|
||||
- **파티 리더** — 플레이어가 RPG 맵에서 걸을 때 쓰는 시트의 캐릭터입니다. 리더는 게임의 `stats.player`가 가리키는 캐릭터이고, 없으면 전투 파티의 첫 번째 캐릭터입니다. 블록에는 열린 캐릭터가 "Party leader"인지 "Not the party leader"인지 표시됩니다. 리더를 바꾸는 버튼은 아직 없습니다. 컬렉션의 설정이며 모드 관리자에서 바꿉니다.
|
||||
- **계산된 전투 수치** — 캐릭터에 `Stats`가 있으면 각 스탯의 값과 전투 수치를 보여 줍니다. 힌트는 체력, 공격, 방어가 스탯에서 온다고 알려 주므로, 이 칸이 아니라 스탯을 편집해야 합니다. `Stats`가 있는 캐릭터에서 **Health**, **Attack**, **Defence**는 읽기 전용입니다. `Stats`가 없으면 블록에 그렇게 표시되고, 전투 수치는 위 칸의 값입니다.
|
||||
- **말을 걸면 일행에 합류** — 체크하면 합류 시나리오 `scenarios/<내 모드>/party/<id>.scenario`를 씁니다. 플래그 `<id>_joined`를 1로 설정하고 캐릭터를 일행에 넣습니다(`action party.add`). 체크를 해제하면 파일을 바로 지웁니다. 리더는 합류하지 않습니다(체크박스 비활성). 맵에서 동료로 쓰려면 RPG 맵 편집기의 「캐릭터」 탭에서 배치하세요. 배치한 액터에게 말을 걸면 합류하고, 액터는 자기 칸을 떠나며, 동료는 주인공 뒤를 따라 걷습니다.
|
||||
|
||||
## 문제가 생겼을 때
|
||||
|
||||
1. **체력이나 공격을 바꿔도 효과가 없습니다.** 게임은 스탯에서 수치를 계산합니다. RPG Plus가 자기 파티에 하는 것처럼.
|
||||
2. **캐릭터가 RPG 맵 에디터의 "캐릭터" 탭에 없습니다.** 이 탭은 전투 스탯이 있는 캐릭터를 나열합니다. 어떤 스프라이트든 "Appearance" 탭에서 배치할 수 있습니다.
|
||||
2. **캐릭터가 RPG 맵 편집기 팔레트에 없습니다.** 「캐릭터」 탭은 걷기 스프라이트(**Charset**)가 있는 캐릭터만 보여 줍니다. 없으면 배치할 수 없습니다. 「액터」 탭은 게임 캐릭터가 아니라 `rpg_object`의 액터 오브젝트를 보여 줍니다.
|
||||
3. **모드 목록이 비어 있습니다.** 압축된 모드는 편집할 수 없습니다.
|
||||
+20
-6
@@ -6,9 +6,9 @@ Characters Editor правит персонажей мода, пока игра
|
||||
|
||||
## Правка и её результат в игре
|
||||
|
||||
В RPG Plus героем деревни выступает персонаж `rpg_hero` мода `rpg_demo_game`. Выберите этот мод сверху, укажите **Героя**, введите новое английское имя и нажмите **Сохранить** (Ctrl+S):
|
||||
В RPG Plus героем деревни выступает персонаж `rpg_hero` мода `rpg_plus_game`. Выберите этот мод сверху, укажите **Героя**, введите новое английское имя и нажмите **Сохранить** (Ctrl+S):
|
||||
|
||||

|
||||

|
||||
|
||||
Изменилась только английская строка в `locale/en.properties` мода. Участник отряда на панели персонажей сразу после:
|
||||
|
||||
@@ -21,21 +21,35 @@ Characters Editor правит персонажей мода, пока игра
|
||||
- **Id** — id персонажа; по нему находят его сценарии, отряды, бои и карты.
|
||||
- **Имя** — ключ перевода и строка на каждый язык мода.
|
||||
- **Портрет** — картинка на карточках и панелях; **…** открывает сетку для выбора.
|
||||
- **Чарсет (RPG)** — спрайт ходьбы на RPG-картах (3 кадра × 4 направления). Редактор RPG-карт предлагает персонажей вместе с их чарсетом для размещения.
|
||||
- **Чарсет (RPG)** — спрайт ходьбы на RPG-картах (3 кадра × 4 направления).
|
||||
- **Уровень**, **Здоровье**, **Атака**, **Защита**, **Очки действий**, **Опыт** — боевые числа персонажа.
|
||||
- **Шанс вербовки** — от 0 до 100: вероятность забрать персонажа в отряд после победы над ним (см. Recruiting).
|
||||
- **Поведение** и **Действия** — как персонаж сражается и какие у него боевые действия.
|
||||
- **Добыча** — что выпадает, когда персонажа побеждают как врага: список строк, в каждой предмет (пикер известных игре предметов), минимум и максимум количества и шанс от 0 до 100.
|
||||
- **Id** сохранённого персонажа здесь не меняется напрямую; **Переименовать…** под ним меняет id (см. ниже).
|
||||
- **Поля других модов** — поля, которые другие моды описывают для персонажей в своих схемах (например, класс, характеристики и черты из Stats Engine), появляются отдельной секцией.
|
||||
- **Прочие поля** — остальное из JSON персонажа, правится как JSON и сохраняется как есть.
|
||||
|
||||
Панель инструментов: **Новый** (Ctrl+N), **Копия** (Ctrl+D), **Удалить**, **Отменить**/**Повторить** (Ctrl+Z / Ctrl+Y), **Сохранить** — записываются только изменённые файлы; тексты уходят в файлы локализации мода.
|
||||
|
||||
## Каких персонажей можно править
|
||||
## Персонажи других модов
|
||||
|
||||
В списке — персонажи из собственных файлов выбранного мода; предлагаются только моды, установленные папками. Персонажей чужих модов в списке нет, и их файлы никогда не записываются. Чтобы изменить такого персонажа, дайте в своём моде тот же id с зависимостью от владельца или добавьте поля патчем.
|
||||
Список показывает персонажей выбранного мода. Отметьте **Entries of other mods**, чтобы добавить персонажей его зависимостей; они помечены `↗ владелец`. Правка такого персонажа записывается патчем в ваш мод (`patches/character/<ваш мод>.json`) только с изменёнными значениями; файл владельца остаётся побайтно прежним. **Reset to inherited** убирает патч, а **↺** рядом с полем убирает ваше значение этого поля. Писать можно только в моды, установленные папкой.
|
||||
|
||||
## Переименование id
|
||||
|
||||
**Переименовать…** под Id сохранённого персонажа спрашивает новый id и перечисляет все файлы, которые называют персонажа, до записи: его собственный файл, сценарии, которые дают его в партию или начинают с ним бой, расстановки и карты, где он стоит. Файлы других модов только перечисляются и не меняются. **Переименовать** сначала сохраняет правки; **Отменить переименование** возвращает все изменённые файлы точно такими, какими они были. Id: латинские буквы, цифры, `_`, `-` и `/` между частями, свободный во всех модах.
|
||||
|
||||
## Блок «Партия»
|
||||
|
||||
Под полями блок «Партия» показывает два пункта:
|
||||
|
||||
- **Лидер партии** — персонаж, с листом которого игрок ходит по RPG-картам. Лидер — тот, кого называет `stats.player` игры; если его нет, первый персонаж боевого состава. Блок пишет «Party leader» или «Not the party leader» для открытого персонажа. Назначить нового лидера кнопкой пока нельзя: это настройка коллекции, её меняют через менеджер модов.
|
||||
- **Вычисленные боевые числа** — если у персонажа есть `Stats`, значения статов и боевые числа. Подсказка говорит, что здоровье, атака и защита берутся из статов, поэтому правьте статы, а не эти поля. У персонажа со `Stats` поля **Health**, **Attack** и **Defence** только для чтения. Без `Stats` блок так и пишет, а боевые числа — это поля выше.
|
||||
- **Присоединяется к отряду при разговоре** — отметьте, чтобы записать сценарий присоединения `scenarios/<ваш мод>/party/<id>.scenario`: он ставит флаг `<id>_joined` в 1 и добавляет персонажа в отряд (`action party.add`). Снятие отметки сразу удаляет файл. Лидер не присоединяется: флажок для него выключен. Если у объекта-актёра персонажа уже есть диалог (его взаимодействие открывает сценарий или имеет свои строки), присоединение идёт после этого диалога: диалог проигрывается, затем персонаж присоединяется, а диалог не заменяется. Так записывает редактор карт, когда персонаж выбран во вкладке «Персонажи». Чтобы персонаж стал напарником на карте, поставьте его во вкладке «Персонажи» редактора RPG-карт: разговор с поставленным актёром присоединяет его, актёр уходит с клетки, а напарник идёт за героем.
|
||||
|
||||
## Если что-то пошло не так
|
||||
|
||||
1. **Изменённые здоровье или атака не действуют.** Игра вычисляет числа из характеристик, как RPG Plus делает для своего отряда.
|
||||
2. **Персонажа нет на вкладке «Персонажи» редактора RPG-карт.** На вкладке — персонажи с боевыми характеристиками; спрайт для размещения можно взять на вкладке «Внешность».
|
||||
2. **Персонажа нет в палитре редактора RPG-карт.** Вкладка «Персонажи» показывает только персонажей с ходячим спрайтом (**Charset**); без него персонажа не поставить. Вкладка «Актёры» показывает объекты `rpg_object`, а не персонажей игры.
|
||||
3. **Список модов пуст.** Упакованные моды не редактируются.
|
||||
+14
-6
@@ -6,9 +6,9 @@ Nó mở từ hộp công cụ (chiếc búa trên thanh công cụ) dưới tê
|
||||
|
||||
## Một chỉnh sửa và kết quả trong game
|
||||
|
||||
Trong RPG Plus, anh hùng của ngôi làng là nhân vật `rpg_hero` của mod `rpg_demo_game`. Chọn mod đó ở trên, chọn **Anh hùng**, gõ một tên tiếng Anh mới rồi nhấn **Lưu** (Ctrl+S):
|
||||
Trong RPG Plus, anh hùng của ngôi làng là nhân vật `rpg_hero` của mod `rpg_plus_game`. Chọn mod đó ở trên, chọn **Anh hùng**, gõ một tên tiếng Anh mới rồi nhấn **Lưu** (Ctrl+S):
|
||||
|
||||

|
||||

|
||||
|
||||
Chỉ dòng tiếng Anh trong `locale/en.properties` của mod thay đổi. Ngay sau đó, thành viên tổ đội trên bảng nhân vật:
|
||||
|
||||
@@ -21,7 +21,7 @@ Bảng hiện HP 42 và ATK 12 trong khi tệp ghi 24 và 6: trong RPG Plus, l
|
||||
- **Id** — id của nhân vật; kịch bản, tổ đội, trận đấu và bản đồ tìm nó qua id này.
|
||||
- **Tên** — khóa dịch và một dòng cho mỗi ngôn ngữ của mod.
|
||||
- **Chân dung** — hình trên thẻ và bảng; **…** mở lưới để chọn.
|
||||
- **Charset (RPG)** — sprite đi bộ trên bản đồ RPG (3 khung × 4 hướng). Trình sửa bản đồ RPG đưa ra các nhân vật kèm charset của họ để đặt.
|
||||
- **Charset (RPG)** — sprite đi bộ trên bản đồ RPG (3 khung × 4 hướng).
|
||||
- **Cấp độ**, **Máu**, **Tấn công**, **Phòng thủ**, **Điểm hành động**, **Kinh nghiệm** — các con số chiến đấu của nhân vật.
|
||||
- **Tỉ lệ chiêu mộ** — từ 0 đến 100: khả năng thu nhận nhân vật sau khi đánh bại nó (xem Recruiting).
|
||||
- **Hành vi** và **Hành động** — nhân vật đánh thế nào và có những hành động chiến đấu nào.
|
||||
@@ -30,12 +30,20 @@ Bảng hiện HP 42 và ATK 12 trong khi tệp ghi 24 và 6: trong RPG Plus, l
|
||||
|
||||
Thanh công cụ: **Mới** (Ctrl+N), **Sao chép** (Ctrl+D), **Xóa**, **Hoàn tác**/**Làm lại** (Ctrl+Z / Ctrl+Y), **Lưu** — chỉ những tệp thay đổi được ghi; văn bản vào các tệp bản địa hóa của mod.
|
||||
|
||||
## Những nhân vật nào được sửa
|
||||
## Nhân vật của mod khác
|
||||
|
||||
Danh sách chứa các nhân vật trong tệp của chính mod được chọn; chỉ có các mod cài dưới dạng thư mục được đưa ra. Nhân vật của mod khác không có trong danh sách và tệp của họ không bao giờ bị ghi. Muốn đổi một nhân vật như vậy, hãy mang cùng id trong mod của mình kèm phụ thuộc vào chủ sở hữu, hoặc thêm trường bằng bản vá.
|
||||
Danh sách hiển thị nhân vật của mod đã chọn. Đánh dấu **Entries of other mods** để thêm nhân vật của các mod phụ thuộc, có ghi `↗ chủ sở hữu`. Sửa một nhân vật như vậy sẽ ghi một bản vá vào mod của bạn (`patches/character/<mod của bạn>.json`) chỉ với các giá trị đã đổi; tệp của chủ sở hữu giữ nguyên từng byte. **Reset to inherited** xóa bản vá, còn **↺** cạnh một trường xóa giá trị của bạn ở trường đó. Chỉ ghi được vào các mod được cài đặt dưới dạng thư mục.
|
||||
|
||||
## Khối đội hình
|
||||
|
||||
Bên dưới các trường, khối đội hình hiển thị hai điều:
|
||||
|
||||
- **Đội trưởng** — nhân vật mà người chơi dùng hồ sơ khi đi trên bản đồ RPG. Đội trưởng là nhân vật mà `stats.player` của trò chơi chỉ định; nếu không có, là nhân vật đầu tiên của đội hình chiến đấu. Khối hiển thị *Party leader* hoặc *Not the party leader* cho nhân vật đang mở. Hiện chưa có nút đặt đội trưởng khác: đó là thiết lập của bộ sưu tập, đổi qua trình quản lý mod.
|
||||
- **Các chỉ số chiến đấu đã tính** — nếu nhân vật có `Stats`, hiển thị từng chỉ số kèm giá trị và số chiến đấu. Gợi ý nói rằng máu, công và thủ lấy từ chỉ số, nên hãy sửa chỉ số chứ không sửa các trường này. Khi có `Stats`, **Health**, **Attack** và **Defence** chỉ đọc. Không có `Stats` thì khối nói rõ điều đó và chỉ số chiến đấu là các trường phía trên.
|
||||
- **Gia nhập đội khi nói chuyện** — đánh dấu để ghi kịch bản gia nhập `scenarios/<mod của bạn>/party/<id>.scenario`: nó đặt cờ `<id>_joined` thành 1 và thêm nhân vật vào đội (`action party.add`). Bỏ đánh dấu sẽ xóa tệp ngay. Đội trưởng không bao giờ gia nhập (ô này bị khóa). Để nhân vật thành đồng đội trên bản đồ, hãy đặt nó từ tab **Nhân vật trò chơi** của Trình chỉnh sửa bản đồ RPG: nói chuyện với actor đã đặt sẽ khiến nó gia nhập, actor rời ô của nó, và đồng đội đi theo sau nhân vật chính.
|
||||
|
||||
## Khi có trục trặc
|
||||
|
||||
1. **Đổi máu hay tấn công không có tác dụng.** Game tính các con số từ chỉ số, như RPG Plus làm với tổ đội của nó.
|
||||
2. **Nhân vật không có ở thẻ Nhân vật của trình sửa bản đồ RPG.** Thẻ này liệt kê các nhân vật có chỉ số chiến đấu; sprite nào cũng đặt được từ thẻ Appearance.
|
||||
2. **Nhân vật không có trong bảng đối tượng của Trình chỉnh sửa bản đồ RPG.** Tab **Nhân vật trò chơi** chỉ liệt kê nhân vật có bộ hình đi (**Charset**); không có thì không đặt được. Tab **Nhân vật** (actor) liệt kê các đối tượng actor của `rpg_object`, không phải nhân vật của trò chơi.
|
||||
3. **Danh sách mod trống.** Mod đóng gói không sửa được.
|
||||
+14
-6
@@ -6,9 +6,9 @@ Characters Editor 在游戏运行时编辑模组的角色:各种语言的名
|
||||
|
||||
## 一次编辑及其在游戏中的结果
|
||||
|
||||
RPG Plus 里村庄的英雄是模组 `rpg_demo_game` 的角色 `rpg_hero`。顶部选择该模组,选**英雄**,输入新的英文名称,按**保存**(Ctrl+S):
|
||||
RPG Plus 里村庄的英雄是模组 `rpg_plus_game` 的角色 `rpg_hero`。顶部选择该模组,选**英雄**,输入新的英文名称,按**保存**(Ctrl+S):
|
||||
|
||||

|
||||

|
||||
|
||||
只有模组 `locale/en.properties` 的英文一行变了。紧接着角色面板上的队伍成员:
|
||||
|
||||
@@ -21,7 +21,7 @@ RPG Plus 里村庄的英雄是模组 `rpg_demo_game` 的角色 `rpg_hero`。顶
|
||||
- **Id** —— 角色的 id;剧本、队伍、战斗和地图都靠它找到角色。
|
||||
- **名称** —— 翻译键和模组每种语言的一行文字。
|
||||
- **立绘** —— 卡片和面板上的图片;**…** 打开网格挑选。
|
||||
- **行走图(RPG)** —— 角色在 RPG 地图上的行走图(3 帧 × 4 朝向)。RPG 地图编辑器会把带行走图的角色列为可放置对象。
|
||||
- **行走图(RPG)** —— 角色在 RPG 地图上的行走图(3 帧 × 4 朝向)。
|
||||
- **等级**、**生命**、**攻击**、**防御**、**行动点**、**经验** —— 角色的战斗数值。
|
||||
- **招募几率** —— 0 到 100:击败后收编该角色的几率(见 Recruiting)。
|
||||
- **行为**和**行动** —— 角色怎么打,以及有哪些战斗行动。
|
||||
@@ -30,12 +30,20 @@ RPG Plus 里村庄的英雄是模组 `rpg_demo_game` 的角色 `rpg_hero`。顶
|
||||
|
||||
工具栏:**新建**(Ctrl+N)、**复制**(Ctrl+D)、**删除**、**撤销**/**重做**(Ctrl+Z / Ctrl+Y)、**保存** —— 只写改动的文件;文字进入模组的本地化文件。
|
||||
|
||||
## 哪些角色可以编辑
|
||||
## 其他模组的角色
|
||||
|
||||
列表里是所选模组自己文件中的角色;只提供以文件夹安装的模组。其他模组的角色不在列表里,它们的文件也绝不会被写入。想改这样的角色,可以在自己的模组里带上相同的 id 并声明对属主的依赖,或者用补丁添加字段。
|
||||
列表显示所选模组的角色。勾选 **Entries of other mods** 可加入其依赖模组的角色,并标记 `↗ 所有者`。编辑这类角色时,会在你的模组中写入补丁 `patches/character/<你的模组>.json`,只包含你改动的值;所有者的文件逐字节保持不变。**Reset to inherited** 删除补丁,字段旁的 **↺** 删除你对该字段的值。只能写入以文件夹形式安装的模组。
|
||||
|
||||
## 队伍区块
|
||||
|
||||
表单下方的队伍区块显示两项内容:
|
||||
|
||||
- **队长(Party leader)** —— 玩家在 RPG 地图上以其行走图行动的角色。队长是游戏的 `stats.player` 所指的角色;若没有,则是战斗队伍中的第一个角色。该区块会对当前角色显示「Party leader」或「Not the party leader」。目前还没有设置新队长的按钮:这是合集的设置,通过模组管理器修改。
|
||||
- **计算出的战斗数值** —— 角色有 `Stats` 时,列出每个属性及其战斗数值。提示说明生命、攻击和防御来自属性,因此应编辑属性而不是这些字段。带 `Stats` 的角色,**Health**、**Attack** 和 **Defence** 为只读。没有 `Stats` 时,区块会说明,战斗数值即上方字段的值。
|
||||
- **对话时加入队伍** — 勾选后写入加入剧本 `scenarios/<你的模组>/party/<id>.scenario`:它把标志 `<id>_joined` 设为 1,并把角色加入队伍(`action party.add`)。取消勾选会立即删除该文件。队长从不加入(复选框已禁用)。要让角色在地图上成为同伴,请在 RPG 地图编辑器的「游戏角色」标签页放置它:与放置的角色对话即可加入,该角色离开原来的格子,同伴跟在主角身后移动。
|
||||
|
||||
## 出问题了怎么办
|
||||
|
||||
1. **改了生命或攻击没有效果。** 游戏会从属性推算数值,RPG Plus 对自己的队伍就是这样做的。
|
||||
2. **角色不在 RPG 地图编辑器的「角色」标签页。** 该标签页列出带战斗属性的角色;任何行走图都可以从 Appearance 标签页放置。
|
||||
2. **角色不在 RPG 地图编辑器的调色板中。** 「游戏角色」标签页只列出有行走图(**Charset**)的角色,没有行走图就无法放置。「角色」标签页(Actors)列出的是 `rpg_object` 的 actor 对象,不是游戏里的角色。
|
||||
3. **模组列表是空的。** 打包模组不能编辑。
|
||||
@@ -0,0 +1,5 @@
|
||||
tools/characters_editor/join_check = Joins the party when talked to
|
||||
tools/characters_editor/join_tip = A companion: once it joins, the character walks behind the hero. Writes or removes this mod's join scenario at once.
|
||||
tools/characters_editor/join_hint = Place this character on a map from the Characters tab of the RPG map editor. Talking to it there makes it join the party; the placed character then leaves the map and walks with the hero. The leader never joins.
|
||||
tools/characters_editor/join_on = Joins the party: the join scenario of {0} is written into this mod.
|
||||
tools/characters_editor/join_off = Joins the party: the join scenario of {0} is removed.
|
||||
@@ -0,0 +1,5 @@
|
||||
tools/characters_editor/join_check = Se une al grupo al hablar con él
|
||||
tools/characters_editor/join_tip = Compañero: una vez unido, el personaje camina detrás del héroe. Escribe o borra de inmediato el guion de unión de este mod.
|
||||
tools/characters_editor/join_hint = Coloca este personaje en un mapa desde la pestaña Personajes del editor de mapas RPG. Hablar con él allí lo une al grupo; el personaje colocado sale del mapa y camina con el héroe. El líder nunca se une.
|
||||
tools/characters_editor/join_on = Se une al grupo: el guion de unión de {0} se escribió en este mod.
|
||||
tools/characters_editor/join_off = Se une al grupo: el guion de unión de {0} se borró.
|
||||
@@ -0,0 +1,5 @@
|
||||
tools/characters_editor/join_check = 話しかけると仲間に加わる
|
||||
tools/characters_editor/join_tip = 仲間: 加わったキャラクターは主人公の後ろを歩きます。このモッドの加入シナリオをすぐ書き込み、または削除します。
|
||||
tools/characters_editor/join_hint = RPGマップエディタの「キャラクター」タブからこのキャラクターをマップに置きます。そこで話しかけると仲間に加わり、置かれたキャラクターはマップから消えて主人公と歩きます。リーダーは決して加わりません。
|
||||
tools/characters_editor/join_on = 仲間に加わる: {0} の加入シナリオをこのモッドに書き込みました。
|
||||
tools/characters_editor/join_off = 仲間に加わる: {0} の加入シナリオを削除しました。
|
||||
@@ -0,0 +1,5 @@
|
||||
tools/characters_editor/join_check = 말을 걸면 일행에 합류
|
||||
tools/characters_editor/join_tip = 동료: 합류하면 캐릭터가 주인공 뒤를 따라 걷습니다. 이 모드의 합류 시나리오를 즉시 쓰거나 삭제합니다.
|
||||
tools/characters_editor/join_hint = RPG 맵 편집기의 '캐릭터' 탭에서 이 캐릭터를 맵에 배치하세요. 거기서 말을 걸면 일행에 합류하고, 배치된 캐릭터는 맵에서 빠져 주인공과 함께 걷습니다. 리더는 합류하지 않습니다.
|
||||
tools/characters_editor/join_on = 일행 합류: {0}의 합류 시나리오를 이 모드에 썼습니다.
|
||||
tools/characters_editor/join_off = 일행 합류: {0}의 합류 시나리오를 삭제했습니다.
|
||||
@@ -0,0 +1,5 @@
|
||||
tools/characters_editor/join_check = Присоединяется к отряду при разговоре
|
||||
tools/characters_editor/join_tip = Спутник: после присоединения персонаж идёт за героем. Сразу записывает или удаляет сценарий присоединения этого мода.
|
||||
tools/characters_editor/join_hint = Поставьте персонажа на карту во вкладке «Персонажи» редактора карт RPG. Разговор с ним там присоединяет его к отряду; поставленный персонаж уходит с карты и идёт за героем. Лидер никогда не присоединяется.
|
||||
tools/characters_editor/join_on = Присоединение к отряду: сценарий присоединения {0} записан в этот мод.
|
||||
tools/characters_editor/join_off = Присоединение к отряду: сценарий присоединения {0} удалён.
|
||||
@@ -0,0 +1,5 @@
|
||||
tools/characters_editor/join_check = Gia nhập đội khi nói chuyện
|
||||
tools/characters_editor/join_tip = Đồng hành: sau khi gia nhập, nhân vật đi theo sau người hùng. Ghi hoặc xoá ngay kịch bản gia nhập của mod này.
|
||||
tools/characters_editor/join_hint = Đặt nhân vật này lên bản đồ từ thẻ Nhân vật của trình soạn bản đồ RPG. Nói chuyện với nhân vật ở đó sẽ khiến nhân vật gia nhập đội; nhân vật đã đặt sẽ rời bản đồ và đi cùng người hùng. Thủ lĩnh không bao giờ gia nhập.
|
||||
tools/characters_editor/join_on = Gia nhập đội: đã ghi kịch bản gia nhập của {0} vào mod này.
|
||||
tools/characters_editor/join_off = Gia nhập đội: đã xoá kịch bản gia nhập của {0}.
|
||||
@@ -0,0 +1,5 @@
|
||||
tools/characters_editor/join_check = 对话时加入队伍
|
||||
tools/characters_editor/join_tip = 同伴:加入后,角色会跟在主角身后行走。立即写入或删除本模组的加入剧本。
|
||||
tools/characters_editor/join_hint = 在RPG地图编辑器的“角色”页签中把该角色放到地图上。在那里与其对话即可加入队伍;放置的角色随后离开地图,跟随主角行走。队长永远不会加入。
|
||||
tools/characters_editor/join_on = 加入队伍:已在本模组中写入 {0} 的加入剧本。
|
||||
tools/characters_editor/join_off = 加入队伍:已删除 {0} 的加入剧本。
|
||||
@@ -20,3 +20,10 @@ tools/characters_editor/behaviour = Behaviour
|
||||
tools/characters_editor/behaviour_tip = How the character acts in battle when the game controls it; base — the usual
|
||||
tools/characters_editor/actions = Actions
|
||||
tools/characters_editor/actions_tip = The character's battle actions from the loaded mods
|
||||
tools/characters_editor/section_party = Party
|
||||
tools/characters_editor/leader_yes = Party leader: the player walks on RPG maps with this character's sheet
|
||||
tools/characters_editor/leader_no = Not the party leader: on RPG maps the player looks like the leader
|
||||
tools/characters_editor/section_computed = Computed battle numbers
|
||||
tools/characters_editor/computed_hint = With Stats, health, attack and defence come from the stats: edit the stats, not these fields.
|
||||
tools/characters_editor/computed_none = No Stats: the battle numbers are the fields above.
|
||||
tools/characters_editor/computed_row = {0}: {1} (battle {2})
|
||||
@@ -20,3 +20,10 @@ tools/characters_editor/behaviour = Comportamiento
|
||||
tools/characters_editor/behaviour_tip = Cómo actúa el personaje en combate cuando lo controla el juego; base: el habitual
|
||||
tools/characters_editor/actions = Acciones
|
||||
tools/characters_editor/actions_tip = Las acciones de combate del personaje de los mods cargados
|
||||
tools/characters_editor/section_party = Grupo
|
||||
tools/characters_editor/leader_yes = Líder del grupo: en los mapas RPG el jugador camina con la apariencia de este personaje
|
||||
tools/characters_editor/leader_no = No es el líder del grupo: en los mapas RPG el jugador tiene la apariencia del líder
|
||||
tools/characters_editor/section_computed = Números de combate calculados
|
||||
tools/characters_editor/computed_hint = Con Stats, la salud, el ataque y la defensa vienen de las estadísticas: edita las estadísticas, no estos campos.
|
||||
tools/characters_editor/computed_none = Sin Stats: los números de combate son los campos de arriba.
|
||||
tools/characters_editor/computed_row = {0}: {1} (en combate {2})
|
||||
@@ -20,3 +20,10 @@ tools/characters_editor/behaviour = 行動パターン
|
||||
tools/characters_editor/behaviour_tip = ゲームが操作するときのバトルでの振る舞い。base——標準
|
||||
tools/characters_editor/actions = アクション
|
||||
tools/characters_editor/actions_tip = 読み込まれた MOD にあるキャラクターのバトルアクション
|
||||
tools/characters_editor/section_party = パーティ
|
||||
tools/characters_editor/leader_yes = パーティのリーダー:RPGマップでプレイヤーはこのキャラクターの姿で歩きます
|
||||
tools/characters_editor/leader_no = リーダーではありません:RPGマップでプレイヤーの姿はリーダーのものになります
|
||||
tools/characters_editor/section_computed = 計算された戦闘数値
|
||||
tools/characters_editor/computed_hint = Stats がある場合、体力・攻撃・防御はステータスから計算されます。これらの欄ではなくステータスを編集してください。
|
||||
tools/characters_editor/computed_none = Stats がないため、戦闘数値は上の欄の値です。
|
||||
tools/characters_editor/computed_row = {0}:{1}(戦闘では {2})
|
||||
@@ -20,3 +20,10 @@ tools/characters_editor/behaviour = 행동 방식
|
||||
tools/characters_editor/behaviour_tip = 게임이 조종할 때 전투에서의 행동 방식. base — 기본
|
||||
tools/characters_editor/actions = 액션
|
||||
tools/characters_editor/actions_tip = 불러온 모드에 있는 캐릭터의 전투 액션
|
||||
tools/characters_editor/section_party = 파티
|
||||
tools/characters_editor/leader_yes = 파티 리더: RPG 맵에서 플레이어는 이 캐릭터의 모습으로 걷습니다
|
||||
tools/characters_editor/leader_no = 파티 리더가 아님: RPG 맵에서 플레이어의 모습은 리더의 모습입니다
|
||||
tools/characters_editor/section_computed = 계산된 전투 수치
|
||||
tools/characters_editor/computed_hint = Stats가 있으면 체력, 공격, 방어는 스탯에서 계산됩니다. 이 칸이 아니라 스탯을 편집하세요.
|
||||
tools/characters_editor/computed_none = Stats가 없으면 전투 수치는 위의 칸 값입니다.
|
||||
tools/characters_editor/computed_row = {0}: {1} (전투 {2})
|
||||
@@ -20,3 +20,10 @@ tools/characters_editor/behaviour = Поведение
|
||||
tools/characters_editor/behaviour_tip = Как персонаж ведёт себя в бою под управлением игры; base — обычное
|
||||
tools/characters_editor/actions = Действия
|
||||
tools/characters_editor/actions_tip = Боевые действия персонажа из загруженных модов
|
||||
tools/characters_editor/section_party = Партия
|
||||
tools/characters_editor/leader_yes = Лидер партии: на картах RPG игрок ходит с внешностью этого персонажа
|
||||
tools/characters_editor/leader_no = Не лидер партии: на картах RPG игрок выглядит как лидер
|
||||
tools/characters_editor/section_computed = Вычисленные боевые числа
|
||||
tools/characters_editor/computed_hint = Если есть Stats, здоровье, атака и защита берутся из статов: меняйте статы, а не эти поля.
|
||||
tools/characters_editor/computed_none = Stats нет: боевые числа — поля выше.
|
||||
tools/characters_editor/computed_row = {0}: {1} (в бою {2})
|
||||
@@ -20,3 +20,10 @@ tools/characters_editor/behaviour = Hành vi
|
||||
tools/characters_editor/behaviour_tip = Cách nhân vật hành động trong trận khi game điều khiển; base — thông thường
|
||||
tools/characters_editor/actions = Hành động
|
||||
tools/characters_editor/actions_tip = Các hành động chiến đấu của nhân vật từ các mod đã tải
|
||||
tools/characters_editor/section_party = Đội
|
||||
tools/characters_editor/leader_yes = Đội trưởng: trên bản đồ RPG, người chơi đi với hình dáng của nhân vật này
|
||||
tools/characters_editor/leader_no = Không phải đội trưởng: trên bản đồ RPG, người chơi có hình dáng của đội trưởng
|
||||
tools/characters_editor/section_computed = Chỉ số chiến đấu được tính
|
||||
tools/characters_editor/computed_hint = Khi có Stats, máu, công và thủ lấy từ chỉ số: hãy sửa chỉ số, không sửa các ô này.
|
||||
tools/characters_editor/computed_none = Không có Stats: chỉ số chiến đấu là các ô phía trên.
|
||||
tools/characters_editor/computed_row = {0}: {1} (trong trận {2})
|
||||
@@ -20,3 +20,10 @@ tools/characters_editor/behaviour = 行为
|
||||
tools/characters_editor/behaviour_tip = 由游戏控制时角色在战斗中的行动方式;base——常规
|
||||
tools/characters_editor/actions = 行动
|
||||
tools/characters_editor/actions_tip = 来自已加载模组的角色战斗行动
|
||||
tools/characters_editor/section_party = 队伍
|
||||
tools/characters_editor/leader_yes = 队长:在 RPG 地图上,玩家以该角色的外观行走
|
||||
tools/characters_editor/leader_no = 不是队长:在 RPG 地图上,玩家的外观取自队长
|
||||
tools/characters_editor/section_computed = 计算出的战斗数值
|
||||
tools/characters_editor/computed_hint = 有 Stats 时,生命、攻击和防御来自属性:请修改属性,而不是这些字段。
|
||||
tools/characters_editor/computed_none = 没有 Stats:战斗数值即上方的字段。
|
||||
tools/characters_editor/computed_row = {0}:{1}(战斗中 {2})
|
||||
+5
-1
@@ -8,9 +8,13 @@
|
||||
"sources": [
|
||||
"src/**/*.cs"
|
||||
],
|
||||
"test_sources": [
|
||||
"tests/*.cs"
|
||||
],
|
||||
"depends": [
|
||||
"editor_tools>=1",
|
||||
"tools_base>=1",
|
||||
"characters_base>=1",
|
||||
"stats_base>=1",
|
||||
"ui_base>=1"
|
||||
],
|
||||
"test_suites": [
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 121 KiB After Width: | Height: | Size: 159 KiB |
@@ -1,13 +1,11 @@
|
||||
using Cthangover.Core.UI.Tool;
|
||||
using Cthangover.Mods.Interface.Tool;
|
||||
using Godot;
|
||||
|
||||
namespace Cthangover.Tools.CharactersEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers the character editor as a tool: it appears in the main menu's tool
|
||||
/// block and (with <see cref="CharacterEditorToolBoxButton"/>)
|
||||
/// the in-game toolbar.
|
||||
/// Registers the character editor window opened from the in-game toolbar
|
||||
/// through <see cref="CharacterEditorToolBoxButton"/>.
|
||||
/// </summary>
|
||||
public class CharacterEditorToolProvider : IToolProvider
|
||||
{
|
||||
@@ -19,8 +17,5 @@ namespace Cthangover.Tools.CharactersEditor
|
||||
|
||||
/// <summary>Creates the window.</summary>
|
||||
public Window CreateWindow() => new CharacterEditorWindow();
|
||||
|
||||
/// <summary>Adds the launcher button to the main menu's tool block.</summary>
|
||||
public void AddMenuButton(Container container) => ToolMenuButton.Attach(container, this);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Globalization;
|
||||
using System.Text.Json.Nodes;
|
||||
using Cthangover.Core.Characters;
|
||||
using Cthangover.Core.Games;
|
||||
using Cthangover.Core.Mods.Resolvers;
|
||||
using Cthangover.Core.Settings;
|
||||
using Cthangover.Mods.Stats;
|
||||
using Cthangover.Tools.Common;
|
||||
using Cthangover.Tools.EntityEditor;
|
||||
using Godot;
|
||||
|
||||
namespace Cthangover.Tools.CharactersEditor
|
||||
{
|
||||
@@ -17,6 +23,15 @@ namespace Cthangover.Tools.CharactersEditor
|
||||
/// battle actions offered from the loaded <c>action</c> entities. Loot and
|
||||
/// other mods' fields are "other fields" of the base window. New characters go
|
||||
/// to <c>characters/<mod>.json</c>.
|
||||
/// <para>
|
||||
/// Plan 12.5: the panel under the form marks the party leader (the character
|
||||
/// whose <c>Charset</c> the player walks with on RPG maps: the game setting
|
||||
/// <c>stats.player</c>, else the first battle-set member, as <c>RpgPlayerLook</c>
|
||||
/// reads it) and shows the values a character's <c>Stats</c> compute. A character
|
||||
/// with <c>Stats</c> gets its health, attack and defence from them, so those three
|
||||
/// fields are read-only here (validator rule <c>STAT_FIELD_OVERRIDDEN</c>, plan 6.4).
|
||||
/// Setting the leader is the game settings' job (mod manager), not a button here.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public partial class CharacterEditorWindow : EntityEditorWindow
|
||||
{
|
||||
@@ -31,9 +46,9 @@ namespace Cthangover.Tools.CharactersEditor
|
||||
new EntityField { Key = "Image", LabelKey = "tools/characters_editor/image", TooltipKey = "tools/characters_editor/image_tip", Kind = EntityFieldKind.Picture, Group = "characters" },
|
||||
new EntityField { Key = "Charset", LabelKey = "tools/characters_editor/charset", TooltipKey = "tools/characters_editor/charset_tip", Kind = EntityFieldKind.Picture, Group = "charsets" },
|
||||
new EntityField { Key = "Level", LabelKey = "tools/characters_editor/level", Kind = EntityFieldKind.Integer },
|
||||
new EntityField { Key = "Health", LabelKey = "tools/characters_editor/health", Kind = EntityFieldKind.Integer },
|
||||
new EntityField { Key = "Attack", LabelKey = "tools/characters_editor/attack", Kind = EntityFieldKind.Integer },
|
||||
new EntityField { Key = "Defence", LabelKey = "tools/characters_editor/defence", Kind = EntityFieldKind.Integer },
|
||||
new EntityField { Key = "Health", LabelKey = "tools/characters_editor/health", Kind = EntityFieldKind.Integer, Locked = HasStats },
|
||||
new EntityField { Key = "Attack", LabelKey = "tools/characters_editor/attack", Kind = EntityFieldKind.Integer, Locked = HasStats },
|
||||
new EntityField { Key = "Defence", LabelKey = "tools/characters_editor/defence", Kind = EntityFieldKind.Integer, Locked = HasStats },
|
||||
new EntityField { Key = "Point", LabelKey = "tools/characters_editor/point", TooltipKey = "tools/characters_editor/point_tip", Kind = EntityFieldKind.Integer },
|
||||
new EntityField { Key = "Exp", LabelKey = "tools/characters_editor/exp", TooltipKey = "tools/characters_editor/exp_tip", Kind = EntityFieldKind.Integer },
|
||||
new EntityField { Key = "RecruitmentChance", LabelKey = "tools/characters_editor/recruitment", TooltipKey = "tools/characters_editor/recruitment_tip", Kind = EntityFieldKind.Integer },
|
||||
@@ -44,6 +59,114 @@ namespace Cthangover.Tools.CharactersEditor
|
||||
private static IEnumerable<string> Actions()
|
||||
=> (Entities.Collect<ActionCharacterInfo>()?.Keys ?? Enumerable.Empty<string>()).OrderBy(id => id, StringComparer.Ordinal);
|
||||
|
||||
/// <summary>A character with <c>Stats</c> gets its bound battle numbers from the stats (see the class summary).</summary>
|
||||
private static bool HasStats(JsonObject data) => data["Stats"] != null;
|
||||
|
||||
/// <summary>The party leader's id, as <c>RpgPlayerLook.LeaderId</c> reads it; null without one.</summary>
|
||||
public static string LeaderId()
|
||||
{
|
||||
var setting = ActiveGame.GetSetting(PlayerSetting);
|
||||
if (!string.IsNullOrWhiteSpace(setting))
|
||||
return setting.Trim();
|
||||
var roster = GameData.Instance?.Runtime?.CharacterData;
|
||||
return roster?.Characters.Keys.FirstOrDefault(id => roster.BattleSet.Contains(id));
|
||||
}
|
||||
|
||||
private const string PlayerSetting = "stats.player";
|
||||
|
||||
// Created by CreatePreviewBlock, which the base window calls while it builds (before this class's constructor body): no initialisers.
|
||||
private Label leaderLabel;
|
||||
private VBoxContainer computedBox;
|
||||
private CheckBox joinBox;
|
||||
private string shownId;
|
||||
|
||||
/// <summary>The party section and the computed battle numbers, below the fields.</summary>
|
||||
protected override Control CreatePreviewBlock()
|
||||
{
|
||||
var block = new VBoxContainer { SizeFlagsHorizontal = Control.SizeFlags.ExpandFill };
|
||||
block.AddChild(ToolUi.Section("tools/characters_editor/section_party"));
|
||||
leaderLabel = ToolUi.Hint(string.Empty);
|
||||
leaderLabel.AutowrapMode = TextServer.AutowrapMode.WordSmart;
|
||||
block.AddChild(leaderLabel);
|
||||
joinBox = new CheckBox { Name = "JoinsParty", Text = ToolUi.Tr("tools/characters_editor/join_check"), TooltipText = ToolUi.Tr("tools/characters_editor/join_tip") };
|
||||
joinBox.Toggled += OnJoinToggled;
|
||||
block.AddChild(joinBox);
|
||||
var joinHint = ToolUi.Hint(ToolUi.Tr("tools/characters_editor/join_hint"));
|
||||
joinHint.AutowrapMode = TextServer.AutowrapMode.WordSmart;
|
||||
block.AddChild(joinHint);
|
||||
block.AddChild(ToolUi.Section("tools/characters_editor/section_computed"));
|
||||
block.AddChild(ToolUi.Hint(ToolUi.Tr("tools/characters_editor/computed_hint")));
|
||||
computedBox = new VBoxContainer { SizeFlagsHorizontal = Control.SizeFlags.ExpandFill };
|
||||
block.AddChild(computedBox);
|
||||
return block;
|
||||
}
|
||||
|
||||
/// <summary>Refreshes the leader mark and the computed numbers for the shown character.</summary>
|
||||
protected override void OnSelectionChanged(EntityRecord record)
|
||||
{
|
||||
if (leaderLabel == null || computedBox == null)
|
||||
return;
|
||||
shownId = record?.Id;
|
||||
leaderLabel.Text = record == null ? string.Empty
|
||||
: ToolUi.Tr(record.Id == LeaderId() ? "tools/characters_editor/leader_yes" : "tools/characters_editor/leader_no");
|
||||
if (joinBox != null)
|
||||
{
|
||||
// The leader is the protagonist (stats.player): it never joins, and the check box says so.
|
||||
joinBox.SetPressedNoSignal(record != null && CompanionScenario.Exists(ModId, record.Id));
|
||||
joinBox.Disabled = record == null || record.Id == LeaderId();
|
||||
}
|
||||
foreach (var child in computedBox.GetChildren())
|
||||
{
|
||||
computedBox.RemoveChild(child);
|
||||
child.QueueFree();
|
||||
}
|
||||
if (record == null || !HasStats(record.Data))
|
||||
{
|
||||
computedBox.AddChild(ToolUi.Hint(ToolUi.Tr("tools/characters_editor/computed_none")));
|
||||
return;
|
||||
}
|
||||
foreach (var definition in StatsService.Definitions.Where(d => !string.IsNullOrEmpty(d.Binds)))
|
||||
{
|
||||
var row = string.Format(CultureInfo.InvariantCulture, ToolUi.Tr("tools/characters_editor/computed_row"),
|
||||
ToolUi.Tr(definition.Name), StatValue(record.Id, definition.ID), definition.Binds);
|
||||
computedBox.AddChild(ToolUi.Hint(row));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes or removes the join scenario of the shown character (plan 14.G7) at once: the file is the whole change, the
|
||||
/// map actor reads it the next time the character is chosen in the RPG map editor.
|
||||
/// </summary>
|
||||
private void OnJoinToggled(bool on)
|
||||
{
|
||||
if (string.IsNullOrEmpty(shownId) || shownId == LeaderId())
|
||||
return;
|
||||
var written = on ? CompanionScenario.Write(ModId, shownId) : CompanionScenario.Remove(ModId, shownId);
|
||||
if (!written)
|
||||
{
|
||||
SetStatus(ToolUi.Tr("tools/common/readonly"), Cthangover.Mods.Interface.Tool.ToolStatusKind.Error);
|
||||
joinBox.SetPressedNoSignal(!on);
|
||||
return;
|
||||
}
|
||||
Cthangover.Core.Mods.ModManager.Instance.GetResolver<ScenarioResolver>()?.ClearCache();
|
||||
SetStatus(string.Format(ToolUi.Tr(on ? "tools/characters_editor/join_on" : "tools/characters_editor/join_off"), shownId),
|
||||
Cthangover.Mods.Interface.Tool.ToolStatusKind.Ok);
|
||||
}
|
||||
|
||||
/// <summary>The character's sheet value of <paramref name="stat"/> (integer, invariant), or "-" when no sheet can be made.</summary>
|
||||
private static string StatValue(string characterId, string stat)
|
||||
{
|
||||
try
|
||||
{
|
||||
var sheet = StatsService.Sheet(characterId);
|
||||
return sheet != null && sheet.Has(stat) ? sheet.Rounded(stat).ToString(CultureInfo.InvariantCulture) : "-";
|
||||
}
|
||||
catch (System.Exception)
|
||||
{
|
||||
return "-";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>A level 1 fighter with a plain attack; the portrait is the author's to pick.</summary>
|
||||
protected override JsonObject CreateEntity(string id) => new()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
namespace Cthangover.Tools.CharactersEditor
|
||||
{
|
||||
using Cthangover.Tools.Services;
|
||||
|
||||
/// <summary>
|
||||
/// The join scenario of a character (plan 14.G7): <c>scenarios/<mod>/party/<id>.scenario</c>, which sets the join
|
||||
/// flag and runs <c>action party.add</c>. The "Joins the party" block of this editor writes or removes it. The rpg
|
||||
/// editor reads it when it makes the character's map actor (<c>RpgCharacterActors</c> in <c>rpg_editor</c>), which
|
||||
/// takes the scenario key and the flag from the same convention: change both together.
|
||||
/// </summary>
|
||||
public static class CompanionScenario
|
||||
{
|
||||
/// <summary>The file of the join scenario, relative to the mod.</summary>
|
||||
public static string Path(string mod, string characterId) => "scenarios/" + Key(mod, characterId) + ".scenario";
|
||||
|
||||
/// <summary>The scenario path in the <c>scenarios</c> group, without the extension.</summary>
|
||||
public static string Key(string mod, string characterId) => mod + "/party/" + characterId;
|
||||
|
||||
/// <summary>The story flag the join sets to 1; the map actor of the character hides then.</summary>
|
||||
public static string Flag(string characterId) => characterId + "_joined";
|
||||
|
||||
/// <summary>The text of the scenario: the flag, then the party change.</summary>
|
||||
public static string Text(string characterId)
|
||||
=> "flag " + Flag(characterId) + " 1\naction party.add id=" + characterId + "\nend\n";
|
||||
|
||||
/// <summary>True when the mod has the join scenario of the character.</summary>
|
||||
public static bool Exists(string mod, string characterId)
|
||||
=> !string.IsNullOrEmpty(mod) && !string.IsNullOrEmpty(characterId) && ModFileService.ReadText(mod, Path(mod, characterId)) != null;
|
||||
|
||||
/// <summary>Writes the join scenario; false when the mod is not writable.</summary>
|
||||
public static bool Write(string mod, string characterId) => ModFileService.WriteText(mod, Path(mod, characterId), Text(characterId));
|
||||
|
||||
/// <summary>Removes the join scenario; false when the mod is not writable.</summary>
|
||||
public static bool Remove(string mod, string characterId) => !Exists(mod, characterId) || ModFileService.DeleteFile(mod, Path(mod, characterId));
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "Character Editor Test",
|
||||
"description": "GUI test of the character editor in rpg_plus: opens rpg_demo_game's characters, shows the slime's localized name, adds a character with the New button, types its name, health and RPG charset into the form, saves; the game must know the character with its stats and name at once, and the RPG map editor's characters tab must offer it with its charset. The new file and the locale edits are removed again. Activated by --itest=characters_editor_edit with --game=rpg_plus --new (the prologue is clicked through first).",
|
||||
"description": "GUI test of the character editor in rpg_plus: opens rpg_plus_game's characters, shows the slime's localized name, adds a character with the New button, types its name, health and RPG charset into the form, saves; the game must know the character with its stats and name at once. The new file and the locale edits are removed again. Activated by --itest=characters_editor_edit with --game=rpg_plus --new (the prologue is clicked through first).",
|
||||
"sources": [
|
||||
"src/*.cs"
|
||||
],
|
||||
"depends": [
|
||||
"rpg_demo_game>=1",
|
||||
"rpg_plus_game>=1",
|
||||
"rpg_editor>=1"
|
||||
]
|
||||
}
|
||||
@@ -1,38 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Cthangover.Core.Bootstrap;
|
||||
using Cthangover.Core.Characters;
|
||||
using Cthangover.Core.Localization;
|
||||
using Cthangover.Core.Mods;
|
||||
using Cthangover.Core.Mods.Resolvers;
|
||||
using Cthangover.Core.Utils;
|
||||
using Cthangover.Mods.Interface.Tool;
|
||||
using Cthangover.Mods.Interface.View;
|
||||
using Cthangover.Mods.Rpg;
|
||||
using Cthangover.Tools.RpgEditor;
|
||||
using Cthangover.Tools.Services;
|
||||
using Godot;
|
||||
|
||||
namespace Cthangover.Tools.CharactersEditor.Tests
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Cthangover.Core.Bootstrap;
|
||||
using Cthangover.Core.Characters;
|
||||
using Cthangover.Core.Localization;
|
||||
using Cthangover.Core.Mods;
|
||||
using Cthangover.Core.Mods.Resolvers;
|
||||
using Cthangover.Core.Utils;
|
||||
using Cthangover.Mods.Interface.Tool;
|
||||
using Cthangover.Mods.Interface.View;
|
||||
using Cthangover.Tools.Services;
|
||||
using Cthangover.Mods.Rpg.Model;
|
||||
using Cthangover.Tools.RpgEditor;
|
||||
using Godot;
|
||||
|
||||
/// <summary>
|
||||
/// Drives the character editor like an author: the toolbar buttons and the
|
||||
/// form's fields (their change signals), Save. Then the game itself is asked:
|
||||
/// the entity cache must hold the new character with the typed health and its
|
||||
/// action, the translation server its typed name, and the RPG map editor's
|
||||
/// character list must offer it with the typed charset. The new characters
|
||||
/// action, and the translation server its typed name. The new characters
|
||||
/// file is deleted and the mod's locale files are restored afterwards, so
|
||||
/// rpg_demo_game stays as it was.
|
||||
/// rpg_plus_game stays as it was.
|
||||
/// Result line: <c>[TEST_RESULT] name=characters_editor_edit passed=N failed=M</c>.
|
||||
/// </summary>
|
||||
public partial class CharacterEditorTestDriver : Node
|
||||
{
|
||||
private const float TickSeconds = 0.15f;
|
||||
private const float TimeoutSeconds = 60f;
|
||||
private const string Mod = "rpg_demo_game";
|
||||
private const string NewFile = "characters/rpg_demo_game.json";
|
||||
private const string NewId = "rpg_demo_game_new_character";
|
||||
private const string Mod = "rpg_plus_game";
|
||||
private const string NewFile = "characters/rpg_plus_game.json";
|
||||
private const string NewId = "rpg_plus_game_new_character";
|
||||
private const string TypedName = "Тестовый гоблин";
|
||||
|
||||
private readonly List<string> failures = new();
|
||||
@@ -99,8 +98,17 @@ namespace Cthangover.Tools.CharactersEditor.Tests
|
||||
var slime = window.Document.Find("rpg_slime");
|
||||
Check(slime != null, "the demo's characters are listed");
|
||||
window.Select(slime);
|
||||
Check(window.Document.GetText(language, "rpg_demo/character/slime") == TranslationServer.Translate("rpg_demo/character/slime").ToString(),
|
||||
Check(window.Document.GetText(language, "rpg_plus/character/slime") == TranslationServer.Translate("rpg_plus/character/slime").ToString(),
|
||||
$"the form shows the character's name in '{language}'");
|
||||
Check(Row("tools/characters_editor/health").OfType<SpinBox>().First().Editable, "a character without Stats: health is edited");
|
||||
var wolf = window.Document.Find("rpg_wolf");
|
||||
Check(wolf?.Data["Stats"] != null, "the demo's wolf has Stats (its health comes from them)");
|
||||
window.Select(wolf);
|
||||
Check(!Row("tools/characters_editor/health").OfType<SpinBox>().First().Editable
|
||||
&& !Row("tools/characters_editor/attack").OfType<SpinBox>().First().Editable
|
||||
&& !Row("tools/characters_editor/defence").OfType<SpinBox>().First().Editable,
|
||||
"a character with Stats: health, attack and defence are computed, not edited");
|
||||
window.Select(slime);
|
||||
|
||||
Press("tools/entity_editor/new");
|
||||
Check(window.SelectedId == NewId, $"New adds and selects {NewId} (got {window.SelectedId})");
|
||||
@@ -122,8 +130,21 @@ namespace Cthangover.Tools.CharactersEditor.Tests
|
||||
Check(characters.TryGetValue(NewId, out var saved), "the game knows the new character right after saving");
|
||||
Check(saved?.Health == 33 && saved.Actions?.Contains("physics/attack") == true, "with the typed health and its action");
|
||||
Check(TranslationServer.Translate(saved?.Name ?? "-").ToString() == TypedName, $"and the typed name ({saved?.Name})");
|
||||
var offered = RpgCharacterCatalog.Load(new RpgTextures()).FirstOrDefault(e => e.Id == NewId);
|
||||
Check(offered?.Look == "village/slime" && offered.Name == TypedName, $"the RPG map editor offers it with its charset ({offered?.Look})");
|
||||
// plan 14.G7: "Joins the party" writes the join scenario at once; unticking removes it again.
|
||||
var join = window.FindChildren("JoinsParty", "", true, false).OfType<CheckBox>().FirstOrDefault();
|
||||
Check(join != null && !join.Disabled && !join.ButtonPressed, "a new character can join the party (its check box is free and off)");
|
||||
Check(!CompanionScenario.Exists(Mod, NewId), "no join scenario before the tick");
|
||||
join.ButtonPressed = true;
|
||||
var joinText = ModFileService.ReadText(Mod, CompanionScenario.Path(Mod, NewId)) ?? string.Empty;
|
||||
Check(joinText.Contains("flag " + NewId + "_joined 1") && joinText.Contains("action party.add id=" + NewId) && !joinText.Contains("\r"),
|
||||
"the tick writes the join scenario (flag, party.add, LF lines)");
|
||||
join.ButtonPressed = false;
|
||||
Check(!CompanionScenario.Exists(Mod, NewId), "the untick removes the join scenario");
|
||||
// phase 8 (claude_plan.md E4): the RPG map editor opens beside the characters and its actor palette has rows.
|
||||
// It does not list characters yet (plan 12.4 leaves that to a later step), so the new character is not checked there.
|
||||
var rpgEditor = ToolWindow.Open<RpgEditorWindow>();
|
||||
Check(rpgEditor.Palette.Count(RpgObjectForm.Actor) > 0, "the RPG map editor opens and its palette lists actors");
|
||||
rpgEditor.QueueFree();
|
||||
var written = ModFileService.ReadText(Mod, NewFile) ?? string.Empty;
|
||||
Check(written.Contains("\"Kind\": \"character\"") && !written.Contains("\r"), "the new file declares its kind and has LF lines");
|
||||
Check(characterFiles.All(f => ModFileService.ReadText(Mod, f.Key) == f.Value), "the demo's character files are untouched");
|
||||
@@ -166,6 +187,7 @@ namespace Cthangover.Tools.CharactersEditor.Tests
|
||||
var path = ModFileService.GetWritablePath(Mod, NewFile);
|
||||
if (path != null && File.Exists(path))
|
||||
File.Delete(path);
|
||||
CompanionScenario.Remove(Mod, NewId);
|
||||
foreach (var backup in backups)
|
||||
ModFileService.WriteText(Mod, backup.Key, backup.Value);
|
||||
ModManager.Instance.GetResolver<EntityResolver>()?.ClearCache();
|
||||
@@ -215,7 +237,7 @@ namespace Cthangover.Tools.CharactersEditor.Tests
|
||||
{
|
||||
step = -1;
|
||||
GameLogger.Log("TEST", $"[TEST_RESULT] name=characters_editor_edit passed={passed} failed={failures.Count}");
|
||||
GetTree().Quit(failures.Count == 0 ? 0 : 1);
|
||||
Cthangover.Core.Bootstrap.ApplicationExit.Quit(GetTree(), failures.Count == 0 ? 0 : 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
namespace Cthangover.Tools.CharactersEditor.Tests
|
||||
{
|
||||
using Cthangover.Core.Mods.Testing;
|
||||
|
||||
/// <summary>
|
||||
/// The join scenario of a character (plan 14.G7) as text and path: the file the "Joins the party" block writes, and the flag
|
||||
/// and <c>party.add</c> line it holds. The rpg editor reads the same names (<c>RpgCharacterActors</c>): both sides change together.
|
||||
/// </summary>
|
||||
public class CompanionScenarioTests
|
||||
{
|
||||
[ModTest("companion/path_and_key_are_the_party_folder")]
|
||||
static void PathAndKey(ModTestContext ctx)
|
||||
{
|
||||
ModAssert.Equal("scenarios/rpg_plus_game/party/rpg_companion.scenario", CompanionScenario.Path("rpg_plus_game", "rpg_companion"), "the file");
|
||||
ModAssert.Equal("rpg_plus_game/party/rpg_companion", CompanionScenario.Key("rpg_plus_game", "rpg_companion"), "the scenario key");
|
||||
}
|
||||
|
||||
[ModTest("companion/flag_is_the_id_with_joined")]
|
||||
static void Flag(ModTestContext ctx)
|
||||
{
|
||||
ModAssert.Equal("rpg_companion_joined", CompanionScenario.Flag("rpg_companion"), "the join flag");
|
||||
}
|
||||
|
||||
[ModTest("companion/text_sets_the_flag_then_adds_the_party_member")]
|
||||
static void Text(ModTestContext ctx)
|
||||
{
|
||||
ModAssert.Equal("flag rpg_companion_joined 1\naction party.add id=rpg_companion\nend\n", CompanionScenario.Text("rpg_companion"),
|
||||
"the text is LF, the flag first, then party.add");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user