-
-
Notifications
You must be signed in to change notification settings - Fork 2
Dialogue ja
English | 日本語
Dialogue ライブラリです。ファイルは DragNWash.ModFramework.Dialogue.dll、名前空間は DragNWash.ModFramework.Dialogue です。これから表示される台詞や選択肢を、Yarn の台詞 ID、話者、ノードといっしょに受け取れます。ゲームの更新で本文が変わった台詞でも、Mod が自分のデータをもう一度見つけられるように手伝います。
[BepInDependency(GameDialogue.Guid, BepInDependency.DependencyFlags.HardDependency)]GameDialogue.NodeStarted += node => Logger.LogInfo($"Node {node}");
GameDialogue.LineShowing += line =>
Logger.LogInfo($"{line.LineId} {line.Speaker}: {line.Text}");
GameDialogue.OptionShowing += option =>
Logger.LogInfo($"Option {option.LineId} available={option.IsAvailable}: {option.Text}");ハンドラーはテキストが出る直前に呼ばれます。どれかが例外を出してもログに書かれるだけで、ほかのハンドラーはそのまま呼ばれます。
| プロパティ | 意味 |
|---|---|
string LineId |
Yarn の台詞 ID(例:line:6046bedf)。言語が変わっても、誤字修正だけのゲームのアップデートでも変わらない |
string Speaker |
スクリプトに書かれた話者の名前(Ryan)。なければ null。ゲームのスクリプトはほとんどの台詞に話者を書いていないので、ほぼすべての台詞で空になる。下の SpeakerGuess を参照 |
string Text |
名前を除いたテキスト |
string FullText |
スクリプトどおりの名前つきテキスト(Ryan: Hello) |
IReadOnlyList<string> Metadata |
Yarn のタグ(例:lastline) |
string Node |
分かる場合は Yarn のノード |
TMP_Text Component |
テキストが入るコンポーネント |
bool IsOption |
プレイヤーが選べる選択肢なら true |
bool IsAvailable |
選択肢のとき、打ち消し線で選べない状態なら false |
実験的な機能です。 フレームワーク 1.4.0 で入ったもので、この先のバージョンで変わったり、無くなったりするかもしれません。
Dialogue 1.2.0 で、DialogueLine にプロパティが 2 つ増えました。
| プロパティ | 意味 |
|---|---|
string SpeakerGuess |
誰の台詞か。スクリプトに話者が書いてあれば Speaker、なければノード名からの推測(最初の _ より前。Ryan_1_intro なら Ryan)、選択肢なら Kobold(プレイヤー)。手がかりがなければ null |
string SpeakerFrom |
推測の出どころ。script、node、option、または null |
テキストを変えるには Text を使い、どの台詞なのかは書き換え処理の中で TryGetLine を使って確かめます。
GameText.AddRewriter(MyMod.Guid, context =>
{
if (GameDialogue.TryGetLine(context.Component, context.Source, out DialogueLine line)
&& line.LineId == "line:6046bedf")
{
context.Text = "Hello there!";
}
});TryGetLine が合うのは、コンポーネントがまだその台詞(名前つきでも名前なしでも、打ち消し線つきでも)を表示している間だけです。そのあとでコンポーネントが表示するテキストには合いません。
実験的な機能です。 Dialogue ライブラリ 1.1.0(2026-09-17 リリース)で入ったものです。
台詞について何かを覚えておく Mod(翻訳、しおり、チャプターの目印など)は、ゲームが更新されたあとで同じ台詞を見つけ直さないといけません。英文そのものをキーにすると、ちょっと直されただけで見つからなくなります。実際、2026 年 9 月 14 日の更新では 24 行の誤字が直され、その翻訳が全部英語に戻ってしまいました。かといって Yarn の台詞 ID だけをキーにすると、開発元が ID を振り直したり台詞を作り直したりしたときに見つからなくなります。そこで LineKey と LineResolver は 4 種類のキーを持ち、強いものから順に試します。
キーは LineKey が計算します。リポジトリの tools/linekeys.py も、同じ定義で同じキーを計算します。どのキーにも本文は入っていないので、キーをリポジトリに置いてもゲームの台本を配ることにはなりません。
| キー | 定義 | 耐えられる変化 |
|---|---|---|
| 台詞 ID | Yarn の line:xxxxxxxx タグ。DialogueLine.LineId の値 |
本文のどんな修正にも |
| ハッシュ | コンポーネントが受け取った UTF-8 の本文(タグ込み)の SHA-256 の先頭 16 桁 | なし。翻訳パックが使っているキー |
| 正規化ハッシュ | 正規化した本文のハッシュ。<タグ> を外し、ASCII の英字を小文字にし、英数字と空白以外を落とし、連続する空白を 1 つにする |
記号、大文字小文字、空白、TextMeshPro のタグの修正 |
| 指紋 | 正規化した本文の 64 ビット SimHash。3 文字ずつの窓を FNV-1a 64 でハッシュし、ビットごとに投票する | 小さな修正。似た本文は数ビットしか離れない(LineKey.Distance) |
Yarn の台詞 ID は、コンパイラが台本ファイルに一度だけ書き込むタグなので、開発元が本文を直しても残ります。変わるのは、台詞を作り直したときか、台本のタグを振り直したときだけです。
LineResolver は Mod の記録(LineRecord)を持っています。記録には上のキーと、その台詞を見たときのノードと話者、それに好きなペイロードが入ります。Resolve(line, displayedText) を呼ぶと、次の順に探します。
-
台詞 ID。 ID が合う記録があれば、それを採ります。記録のハッシュが画面の本文と違うときは、本文が変わっていて Mod のデータが古いかもしれないので、
NeedsReviewを立てます。 - ハッシュ。 表示される本文そのもので探します。
- 正規化ハッシュ。 合う記録が 1 つだけのときに使います。「Yes.」のように複数の台詞が同じ本文を持つものは、推測しません。
-
あいまい照合。 同じノードの記録の中から(ノードが分からなければ全記録から、ノードに記録がなければ照合しません)、指紋が一番近いものを採ります。ただし、差が 10 ビット以内で、その近さのものが 1 つだけ(同点なら話者で絞り、それでも決まらなければ断ります)、しかも両方の本文が正規化後に 12 文字以上あるときだけです。この場合も
NeedsReviewを立てます。
それ以外は null を返します。間違った台詞を出すくらいなら、何も出さないほうを選びます。
ゲームの台詞 1,839 行で、ゲーム自身のデータを手元だけで使って測りました(リポジトリに置いているのは結果だけです)。
- 9 月 14 日の更新の前後で、消えた台詞 ID は 0 件、ID はそのままで本文が変わった台詞は 24 件でした。つまり台詞 ID だけでも、24 件すべての翻訳を保てたことになります。
- ランダムに選んだ 300 行に 3 種類の修正(1 文字の誤字、記号、大文字小文字)を加えてみたところ、正規化ハッシュと指紋で 68% / 93% / 91% を取り戻せました。残りは、短すぎるか紛らわしいとして断っています。別の台詞に間違って当てたものは 0 件でした。
var resolver = new LineResolver();
// データファイルから:ツールが書いたキーと、その台詞について覚えておくもの。
resolver.Add(new LineRecord { LineId = "line:6046bedf", Hash = "84f325bca745e504", NormalizedHash = "…", Fingerprint = 0x…, NormalizedLength = 10, Node = "Ryan_1_intro", Speaker = "Ryan", Payload = "素晴らしい!" });
GameDialogue.LineShowing += line =>
{
LineMatch match = resolver.Resolve(line, line.FullText);
if (match != null)
{
Use((string)match.Record.Payload);
if (match.NeedsReview) Log($"{line.LineId}: 本文が変わっています。翻訳を確認してください");
}
};画面で見た本文から記録を作るときは、LineResolver.RecordFor(text, lineId, node, speaker, payload) を使えばキーを全部計算してくれます。ゲームの外では python tools/linekeys.py "本文" で同じキーが出せて、python tools/linekeys.py --check で Python 側が ci/linekey-vectors.json と合っているか確かめられます。リポジトリの CI では、C# 側も同じファイルで確かめています。
実験的な機能です。 フレームワーク 1.4.0 で入ったもので、この先のバージョンで変わったり、無くなったりするかもしれません。
Dialogue 1.2.0 は 操作の登録簿 に読み取りの操作を 2 つ登録していて、Console の op コマンドで動かせます。
| 操作 | 返すもの |
|---|---|
dialogue.current |
今の会話:会話が進んでいるか(running)、そのノード、選択肢が画面に出ているか(options_showing)、最後に出た台詞、このゲームのビルドでライブラリが台詞と選択肢を受け取れるか(hooks) |
dialogue.recent |
このセッションで最近出た台詞と選択肢(最大 100 件を保持)。古い順で、それぞれ種類、台詞 ID、ノード、話者、話者の出どころ、本文つき。引数は text(それを含む台詞だけ)と max(1〜100。省略すると 20) |
| メンバー | 意味 |
|---|---|
const string Guid |
"com.tomxv.dragnwash.modframework.dialogue" |
const string Version |
ライブラリのバージョン |
bool LinesAvailable |
台詞のフックが入っていれば true |
bool OptionsAvailable |
選択肢のフックが入っていれば true |
string CurrentNode |
直近に始まった Yarn のノード。なければ null |
- Yarn Spinner の台詞や選択肢の表示部品に自分でパッチを当てること
- ゲームのスクリプトの文章を Mod やリポジトリに含めること。台詞は
LineIdか、上の安定したキーで指定してください
Players
Mod authors
- Getting started
- Playing well with others (the guide)
- Going online
- Installer
- Mod reload
- Overrides (no code)
- Graphs (no code, makes things happen)
Tools (F1, developer tools)
- Inspector
- Console
- Code graph
- Bridge (AI clients, MCP)
API
日本語
- ホーム
- プレイヤー向け · ランチャー · FAQ · クラッシュレポート
- はじめての Mod · ほかの Mod と一緒に動かす · 外と通信する Mod · インストーラー · Mod の再読み込み · Overrides · Graphs
- Inspector · Console · コードのグラフ · Bridge
- 中核 API · 操作の登録簿 · Text · Dialogue · Tool window · Assets · Flags and saves · GameEvents · SettingMeta
Links
- Repository
- Releases
- Changelog
- Design records: DESIGN · ROADMAP · CONTENT_POLICY