クエストトラッカー
クエストの記録を作ります。クエストごとに達成済みかどうかが表示され、プレイヤーの所持金も画面に出て、クエストを達成すると報酬が支払われて通知が出ます。クエストが達成されたかどうかは AI が判断し、報酬はビヘイビアがきっちり 1 回だけ支払い、記録はプレイヤー画面のページで見せます。コードは要りません。
完成するもの
- クエスト記録のページ:「Find Herbs」(薬草探し)と「Defeat the Forest Wolf」(森の狼退治)。それぞれ達成済みか未達成かが表示されます
- 所持金を画面に表示:報酬が入るたびに更新されます
- クエストの達成は AI が記録:物語の中で達成されたら、プレイヤーがどんな言い方をしても AI が記録します
- 報酬は 1 回だけ:薬草で +30 金貨、狼で +50 金貨。通知付き
- 進み具合の表示:「1 / 2 達成」
仕組み
プレイヤーが村の長老に薬草を渡す
→ AI が、変数 Quests done のビヘイビアルールに従って「Find Herbs」をリストに追加
→ ビヘイビア「報酬:Find Herbs」が Quests done を見ている(変数が変化)
→ 条件(Quests done が「Find Herbs」を含む)を満たし、まだ一度も発動していない(最大発動回数 1)
→ Gold +30、通知「クエスト達成:Find Herbs(+30 金貨)」、AI に伝える
→ クエスト記録で Find Herbs が達成済みになる物語の中で何かが起きたかどうかを判断するのは AI が得意で、きっちり 1 回だけ支払うのはエンジンが得意です。
作り方
ステップ 1:変数を作る
カードの下の 追加できるもの から、それぞれ + 変数 を押します。
Quests done
| 項目 | 値 |
|---|---|
| 名前 | Quests done |
| 型 | リスト/表 |
| 初期値 | [] |
| ビヘイビアルール | 下を参照 |
プレイヤーが達成したクエストの名前のリスト。クエストは「Find Herbs」(村の長老に薬草を届ける)と「Defeat the Forest Wolf」(羊をさらっている狼を倒す)。物語の中でプレイヤーが本当に達成したら、その名前をそのままこのリストに追加する。達成していないクエストは追加しない。同じクエストを二度追加しない。Gold
| 項目 | 値 |
|---|---|
| 名前 | Gold |
| 型 | 数値 |
| 初期値 | 0 |
| 範囲 | 0 〜(空欄) |
| ビヘイビアルール | プレイヤーの所持金。クエストの報酬は自動で加算される。戦利品、取引、盗難などで変えてもよい。 |
プレイヤー画面に表示 を押すと、チャット中も Gold がずっと見えます。
Quests completed(なくても OK)
| 項目 | 値 |
|---|---|
| 名前 | Quests completed |
| 型 | 数値 |
| 計算式(自動で計算) | len({Quests done}) |
リストの数を自分で数えてくれます。AI は読めますが、変えることはできません。
ステップ 2:クエストごとに報酬のビヘイビアを作る
追加できるもの から + ビヘイビア を押します。
報酬:Find Herbs
| 部分 | 設定 |
|---|---|
| 発動するとき | 変数が変化:Quests done |
| 次の場合のみ | Quests done 含む Find Herbs |
| 効果 | 変数を変更:Gold 加算 30 |
通知を表示:クエスト達成:Find Herbs(+30 金貨)、スタイル 成功 | |
AIに伝える:プレイヤーはたったいま「Find Herbs」を達成し、30 金貨を受け取った。返信の中でそれに触れること。 | |
| 最大発動回数 | 1 |
報酬が二重に支払われないのは、最大発動回数 が 1 だからです。次のクエストが追加されるとリストはまた変わり、そのときも「Find Herbs を含む」は成り立ちますが、このビヘイビアはもう 1 回発動しています。
AIに伝える は、次の返信に向けて AI にひとこと渡します。これで AI は、長老が硬貨を数えて渡す場面を書けます。
報酬:Defeat the Forest Wolf
同じように作ります。条件は Defeat the Forest Wolf、Gold 加算 50、通知と AI へのひとこともそれに合わせます。
キーワードで発動させる場合
会話の中の言葉でクエストを達成させることもできます。発動するとき:AIがキーワードを発言 長老が薬草を受け取る。キーワードはカンマで区切り、どれか 1 つ が出ればビヘイビアが発動します。なので 倒す, 狼 のように書くと、「狼を見かけた」でも発動してしまいます。その場面ならではのフレーズを使い、クエストごとにスイッチの変数を用意して(効果で true にし、次の場合のみ で確認する)、二度発動しないようにします。プレイヤーの言い方はさまざまなので、上のように AI に記録させるほうがうまく対応できます。
ステップ 3:クエスト記録のページを作る
上部バー中央の プレイヤー画面 を押します。ページを追加 でページを足し(白紙のページ)、名前を「クエスト」にします。
- タイトルの 文字 の部品と、
{Quests completed} / 2 達成と書いた部品を置く(変数の値を挿入… を使います) - リスト の部品を置く。中身の出どころ で 自分で書く を選び、行を 2 つ追加する。タイトル
Find Herbs、本文村の長老に薬草を届ける。報酬:30 金貨。タイトルDefeat the Forest Wolf、本文羊をさらっている狼を倒す。報酬:50 金貨 - 各行をカードで表示 をオンにする
- ロック解除の条件 で 未解除の行をロック表示 をオンにし、見張る変数 を Quests done にして、照合する行の項目 は
titleのままにする。ロック中の表示 にはまだ達成していませんと書く。Quests done がその行のタイトルを含むと、行が明るくなります - 会話のページへ戻る ページへ移動 のボタンを置き、会話のページには ページへ移動 → クエスト の「クエスト」ボタンを置く
編集 をオフにすると、マッシーを使わずにページを押して試せます。
画面全体のレイアウト
金貨やほかの数値をページではなく常に画面に出しておきたいなら、ステータス盤 テンプレート(画面全体 の中)を使うと、ゲージ 4 本、所持金、日数の付いたレイアウトがすぐに手に入ります。
ステップ 4:プレイテスト
上部バーの プレイ を押します。
- クエスト を開く:どちらも「まだ達成していません」、0 / 2 達成、Gold 0
- 薬草を探して持ち帰るまで遊ぶ。AI がクエストを記録すると通知が出て、Gold が 30 になる
- クエスト を開く:Find Herbs が達成済み、1 / 2
- 狼を倒す。Gold が 80 に、2 / 2
プレイテスト右側の このターン で、Quests done がいつ変わったか、報酬のビヘイビアがそれぞれ発動したかがわかります。
うまくいかないときは:
| 症状 | よくある原因 | 直し方 |
|---|---|---|
| 物語では達成したのに記録されない | AI がリストに追加しなかった | ビヘイビアルールで各クエストの名前を正確に書き、何をしたら達成になるかを書く |
| 記録されたのに報酬が出ない | AI が追加した名前が条件と一致しない | リストの項目、条件、行のタイトルをすべて同じ文字にする |
| 報酬が二重に出た | 最大発動回数 が 1 になっていない | 報酬のビヘイビアそれぞれに設定する |
| 記録の行がロックされたまま | 照合する行の項目 か 見張る変数 が違う | title と Quests done にする |
| AI が早すぎるタイミングで達成にする | ルールがゆるすぎる | 何が起きればいいのかを書く:「長老が薬草を手にしたときだけ」 |
カスタムコードの方法:チャットの下のクエストパネル
インターフェースを自分で書くなら、インターフェースのコードで同じ変数を読みます。ここまでの設定はそのままで大丈夫です。
パネル → フロントエンドコード で index.tsx を開き、デフォルトの return <Chat /> を置き換えます。
export default function MyWorld() {
const api = useYumina();
const msgs = api.messages || [];
const done = Array.isArray(api.variables["Quests done"])
? api.variables["Quests done"].map(String)
: [];
const gold = Number(api.variables["Gold"] ?? 0);
const quests = [
{ name: "Find Herbs", reward: 30 },
{ name: "Defeat the Forest Wolf", reward: 50 },
].map((q) => ({ ...q, done: done.includes(q.name) }));
const completedCount = quests.filter((q) => q.done).length;
return (
<Chat renderBubble={(msg) => {
const isLastMsg = msg.messageIndex === msgs.length - 1;
return (
<div>
<div
style={{ color: "#e2e8f0", lineHeight: 1.7 }}
dangerouslySetInnerHTML={{ __html: msg.contentHtml }}
/>
{isLastMsg && (
<div style={{
marginTop: "16px",
padding: "16px",
background: "linear-gradient(135deg, rgba(30,41,59,0.8), rgba(15,23,42,0.9))",
borderRadius: "12px",
border: "1px solid #334155",
}}>
{/* Header with gold */}
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "14px" }}>
<div style={{ fontSize: "15px", fontWeight: "bold", color: "#e2e8f0" }}>Quest Tracker</div>
<div style={{
display: "flex", alignItems: "center", gap: "6px", padding: "4px 12px",
background: "rgba(234,179,8,0.15)", border: "1px solid rgba(234,179,8,0.3)", borderRadius: "20px",
}}>
<span style={{ fontSize: "14px" }}>💰</span>
<span style={{ fontSize: "14px", fontWeight: "bold", color: "#fbbf24" }}>{gold}</span>
</div>
</div>
<div style={{ fontSize: "12px", color: "#64748b", marginBottom: "12px" }}>
Completed {completedCount}/{quests.length}
</div>
{/* Quest list */}
<div style={{ display: "flex", flexDirection: "column", gap: "8px" }}>
{quests.map((quest) => (
<div key={quest.name} style={{
display: "flex", justifyContent: "space-between", alignItems: "center",
padding: "10px 14px", borderRadius: "8px",
background: quest.done ? "rgba(34,197,94,0.08)" : "rgba(30,41,59,0.5)",
border: quest.done ? "1px solid rgba(34,197,94,0.2)" : "1px solid #1e293b",
}}>
<span style={{
fontSize: "13px",
color: quest.done ? "#94a3b8" : "#e2e8f0",
textDecoration: quest.done ? "line-through" : "none",
}}>
{quest.name}
</span>
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
<span style={{ fontSize: "12px", color: quest.done ? "#4ade80" : "#64748b" }}>
{quest.done ? `+${quest.reward} g` : `${quest.reward} g`}
</span>
<span style={{
display: "inline-flex", alignItems: "center", justifyContent: "center",
width: "24px", height: "24px", borderRadius: "6px", fontSize: "13px", fontWeight: "bold",
background: quest.done ? "rgba(34,197,94,0.2)" : "rgba(239,68,68,0.15)",
color: quest.done ? "#4ade80" : "#f87171",
border: quest.done ? "1px solid rgba(34,197,94,0.3)" : "1px solid rgba(239,68,68,0.25)",
}}>
{quest.done ? "✓" : "✗"}
</span>
</div>
</div>
))}
</div>
{completedCount === quests.length && (
<div style={{
marginTop: "12px", padding: "10px", textAlign: "center", fontSize: "13px", fontWeight: "600",
background: "rgba(34,197,94,0.1)", border: "1px solid rgba(34,197,94,0.25)",
borderRadius: "8px", color: "#4ade80",
}}>
All quests complete!
</div>
)}
</div>
)}
</div>
);
}} />
);
}コードがしていること:
api.variables["Quests done"]は変数の名前でリストを読みます。名前がリストに入っていれば、そのクエストは達成済みですapi.variables["Gold"]で所持金を読みますcompletedCountは達成したクエストを数え、進み具合の行と「すべて達成」の帯に使います- パネルは最後のメッセージの下にだけ出て、変数が変わればすぐに更新されます
パネル → フロントエンドコード で、ファイルの横の状態が緑の OK になっていれば大丈夫です。
自分でコードを書きたくないときは
キャンバス右上の AIアシスタント を押して、ほしいパネルを伝えます。
さらに発展させる
クエストを増やす
Quests done のビヘイビアルールにクエストの名前と達成の条件を書き足し、報酬のビヘイビアを追加し、クエスト記録に行を足します(コードなら quests の配列に 1 行)。計算式を使っているなら、記録のページの / 2 を新しい合計に変えます。
AI が出すクエスト
2 つ目のリスト Quests open を追加し、ビヘイビアルールで「キャラクターがプレイヤーに助けを求めたら、クエストを追加する」と AI に伝えます。記録のページには 2 つ目のリストの部品を置き、自分で書いた行の代わりに 変数を読む(Quests open)から表示します。
クエストの連鎖
薬草のあとにだけ「Save the Village」を出したいときは、新しいクエストを待機ロアとして書きます(ビヘイビアにオンにされるまで AI からは見えません)。そのうえでビヘイビアを追加します。Quests done の 変数が変化、次の場合のみ Quests done 含む Find Herbs、効果はその設定の ロアエントリを有効化、最大発動回数 1。それ以降、AI は長老に新しい頼みごとがあることを知っています。次の場合のみ には条件をいくつも入れられ、すべて満たす か いずれか満たす を選べるので、もっと長い連鎖も作れます。待機ロアについてはオープニングと設定を参照してください。
金貨を使う
ショップも同じ Gold の変数を使います。クエストで増やし、ショップで減らす、という形です。
早見表
| やりたいこと | やり方 |
|---|---|
| クエストの達成を AI に判断させる | 各クエストの名前を書いたビヘイビアルールを持つリスト/表の変数 |
| 報酬を 1 回だけ支払う | ビヘイビア:変数が変化、次の場合のみ リストがそのクエストを 含む、最大発動回数 1 |
| プレイヤーに知らせる | 効果:通知を表示、スタイル 成功 |
| AI に知らせる | 効果:AIに伝える(次の返信のみ) |
| 達成したクエストを数える | 計算式 len({Quests done}) の数値の変数 |
| クエスト記録を見せる | 自分で書く 行と、Quests done を見る ロック解除の条件 を設定したリストの部品 |
| 所持金を常に画面に出す | Gold の プレイヤー画面に表示 |
| 決まった言葉でクエストを達成させる | プレイヤーがキーワードを発言 / AIがキーワードを発言(キーワードのどれか 1 つで発動) |
| オリジナルのパネル | 同じ変数を読むインターフェースのコード |
これはレシピ #6 です
AI が何かが起きたことに気づき、ビヘイビアが 1 回だけ支払い、画面がそれを見せる。この流れは、物語の節目、サブクエストの分岐、実績にもそのまま使えます。
