エンディングの作り方(endings)

エンディングは character.json ではなく、events.jsonendings に定義します。31日目に「条件を満たすエンディングの中から1つ」がキャラクターごとに選ばれ、順番に再生されます。

ページ概要

  • 対象ファイル: events.jsonendings) / events/endings/*.json(エンディングスクリプト)
  • 役割: 31日目に再生される「結果イベント(エンディング)」を定義します。
  • どこで使われるか: 31日目のエンディング選出と再生、バリデーション(検証)時
  • 最小構成: このページの「最小構成(コピペ用)」
  • よくあるミス: エンディングを character.json に書いてしまう、priorityの設計ミスで意図と違う結末になる、ID不一致

31日目の選出ルール(重要)

  • キャラクターごとに、そのキャラクターの endings から「発生条件を満たすもの」を集めます。
  • priority が高い順に見て、最初に条件を満たしたエンディングが選ばれます(= 条件が重なる場合は priority が勝つ)。
  • 表示順: 収集されたエンディングは、関係性が低い順に並びます(例: dislike → acquaintance → friend → bestFriend → dating)。

設計のコツ

  • 「上位の結末ほど priority を高く」しておくと、条件が重なっても意図通りになりやすいです。
  • required_conditions は「ゆるい条件→厳しい条件」の順に書くのではなく、priorityで決めるのが安全です。

最小構成(コピペ用)

まずは「常に発生するノーマルエンディング」を1つ置くと、31日目の動作確認が簡単です。

{
  "endings": [
    {
      "id": "ending_normal",
      "title_ja": "いつもの日常",
      "title_en": "As Usual",
      "description_ja": "",
      "description_en": "",
      "type": "normal",
      "required_conditions": {},
      "script_file": "events/endings/ending_normal.json",
      "priority": 0
    }
  ]
}

endings のフィールド

基本はイベント定義と同じですが、type が「エンディング種別」になります。

フィールド 説明
idstring一意ID。スクリプトの event_id と一致が必須。
title_ja / title_enstringエンディング名(推奨: 必須扱いで書く)
description_ja / description_enstring説明(任意)
typestringエンディング種別(例: bad, normal, good, best, true_end
required_conditionsobject発生条件。詳細は イベント発生条件
script_filestringエンディングスクリプト(例: events/endings/ending_normal.json
prioritynumber条件が重なった時にどれを選ぶか(大きいほど優先)
thumbnail_imagestringサムネイル画像(任意)
default_bgmstring開始時BGM(任意)

priority設計の例(意図通りに選ばせる)

「トゥルー > ベスト > グッド > ノーマル」のように、上位ほど priority を高くします。

{
  "endings": [
    {
      "id": "ending_true",
      "title_ja": "トゥルーエンド",
      "title_en": "True End",
      "description_ja": "",
      "description_en": "",
      "type": "true_end",
      "required_conditions": {
        "required_relationship": "dating",
        "stats": {
          "affection": {"operator": ">=", "value": 80},
          "intimacy": {"operator": ">=", "value": 70}
        },
        "required_flags": ["confessed"]
      },
      "script_file": "events/endings/ending_true.json",
      "priority": 300
    },
    {
      "id": "ending_good",
      "title_ja": "グッドエンド",
      "title_en": "Good End",
      "description_ja": "",
      "description_en": "",
      "type": "good",
      "required_conditions": {
        "required_relationship": "friend",
        "stats": { "affection": {"operator": ">=", "value": 50} }
      },
      "script_file": "events/endings/ending_good.json",
      "priority": 200
    },
    {
      "id": "ending_normal",
      "title_ja": "ノーマルエンド",
      "title_en": "Normal End",
      "description_ja": "",
      "description_en": "",
      "type": "normal",
      "required_conditions": {},
      "script_file": "events/endings/ending_normal.json",
      "priority": 0
    }
  ]
}

スクリプト側でやること

エンディングスクリプトも通常のイベントスクリプトと同じ形式です。タイトルを出したい場合は、冒頭にナレーション(dialogue)で文字として表示するなど、スクリプト側で演出してください。

{
  "event_id": "ending_normal",
  "scenes": [
    {
      "scene_id": "t1",
      "type": "dialogue",
      "text_ja": "【いつもの日常】",
      "text_en": "[As Usual]"
    },
    {
      "scene_id": "d1",
      "type": "dialogue",
      "character": "player",
      "text_ja": "春は、また来る。",
      "text_en": "Spring will come again."
    },
    { "scene_id": "end", "type": "end" }
  ]
}

シーンの詳細は イベントスクリプト を参照してください。

よくあるミス

  • endings を character.json に書く: 反映されません。必ず events.json に書きます。
  • priority を同じにする/逆転させる: 条件が重なると「意図と違う結末」になりやすいです。
  • id 不一致: events.jsonid とスクリプトの event_id が一致していない(ENDING_ID_MISMATCH)。
  • script_file が存在しない: MISSING_ENDING_SCRIPT が出ます。