2025年7月26日土曜日

NWN2:EE DLGファイル技術仕様 - 開発者編

⚙️ NWN2:EE DLGファイル技術仕様 - 開発者編

開発者・システム実装者向けのNWN2:EE DLGファイルの詳細技術仕様書です。

🎯 概要

本仕様書では、NWN2:EE DLGファイルの技術的詳細について、実装者向けの詳細な情報を提供します。

📊 バージョン情報

  • GFFバージョン: V3.2
  • 対応エンジン: Neverwinter Nights 2: Enhanced Edition
  • ファイル識別子: "DLG "(4バイト、末尾にスペース)

🏗️ GFFファイル形式詳細

ヘッダ構造

struct GFFHeader {
    char file_type[4];      // "DLG "
    char version[4];        // "V3.2"
    uint32_t struct_offset; // 構造体オフセット
    uint32_t struct_count;  // 構造体数
    uint32_t field_offset;  // フィールドオフセット
    uint32_t field_count;   // フィールド数
    uint32_t label_offset;  // ラベルオフセット
    uint32_t label_count;   // ラベル数
    uint32_t field_data_offset; // フィールドデータオフセット
    uint32_t field_data_count;  // フィールドデータサイズ
    uint32_t field_indices_offset; // フィールドインデックスオフセット
    uint32_t field_indices_count;  // フィールドインデックス数
    uint32_t list_indices_offset;   // リストインデックスオフセット
    uint32_t list_indices_count;    // リストインデックス数
};

フィールドタイプ定義

タイプID タイプ名 サイズ 説明
0 BYTE 1 8ビット符号なし整数
4 DWORD 4 32ビット符号なし整数
5 INT 4 32ビット符号付き整数
8 FLOAT 4 32ビット浮動小数点数
10 CExoString 可変 文字列
11 CResRef 16 リソース参照
12 CExoLocString 可変 ローカライズ文字列
14 Struct 可変 構造体
15 List 可変 リスト

📋 フィールド仕様

ルートレベル基本設定

EndConversation

  • type: CResRef
  • description: 会話終了時に実行されるスクリプト
  • default: "nw_walk_wp"
  • required: true

QuickChat

  • type: INT
  • description: クイックチャットモードの有効/無効
  • values: 0=無効, 1=有効
  • default: 0

DelayReplyF

  • type: FLOAT
  • description: プレイヤーの返答選択肢表示までの遅延時間(秒)
  • range: 0.0 - 10.0
  • default: 0.0

EntryList仕様

必須フィールド

Text:

  • type: CExoLocString
  • description: 表示テキストのStrRef
  • format: [strref, [(language_id, text)]]
  • required: true

Speaker:

  • type: CExoString
  • description: 話者のリソース参照名
  • max_length: 32
  • required: false

Sound:

  • type: CResRef
  • description: 音声ファイルのリソース参照
  • max_length: 16
  • required: false

🔧 スクリプトシステム

ScriptList構造

Script:
  type: CResRef
  description: 実行するスクリプトファイル名
  max_length: 16
  required: true

Parameters:
  type: List
  description: スクリプトパラメータリスト
  required: false

一般的なスクリプト例

スクリプト名 用途 パラメータ
gc_global_int グローバル変数チェック STRING(変数名), STRING(比較値)
gc_is_male 性別チェック(男性) なし
gc_is_female 性別チェック(女性) なし
gc_is_enemy_near 敵の近接チェック FLOAT(距離), INT(チェック方法)

⚡ 条件分岐システム

ActiveConditiona構造

Not:
  type: INT
  description: 条件の否定フラグ
  values: 0=通常条件, 1=NOT条件
  default: 0

And:
  type: INT
  description: 論理演算子
  values: 0=OR演算, 1=AND演算
  default: 1

Script:
  type: CResRef
  description: 条件判定スクリプト
  max_length: 16
  required: true

条件評価ルール

  1. 複数条件の評価順序: リスト内の条件を順番に評価
  2. 論理演算: Andフィールドに基づいてAND/OR演算
  3. NOT条件の処理: Not=1の場合、スクリプト結果を反転
  4. 短絡評価: AND演算でfalseまたはOR演算でtrueが出た時点で評価停止

📹 カメラシステム

CameraInfo詳細構造

フィールド タイプ 説明
ShotType INT ショットタイプ 0=デフォルト, 1=クローズアップ, 2=ミディアム, 3=ロング
StaticCamera CExoString 固定カメラ名 max_length: 32
OverrideMode INT オーバーライドモード 0=なし, 1=あり
MovementType INT 移動タイプ 0=固定, 1=滑らか, 2=瞬間移動

💻 実装ガイドライン

パーサー実装のベストプラクティス

1. エラーハンドリング

def find_field(struct, label, field_type=None):
    for field in struct.value:
        if field.label == label:
            if field_type is None or isinstance(field, field_type):
                return field
    return None

2. 型安全性

def get_int_field(struct, label, default=0):
    field = find_field(struct, label, Field.INT)
    return field.value if field else default

3. データ検証

def validate_entry(entry_struct):
    # 必須フィールドチェック
    text_field = find_field(entry_struct, 'Text', Field.CExoLocString)
    if not text_field:
        raise ValueError("Entry missing required Text field")
    
    # データ範囲チェック
    animation_field = find_field(entry_struct, 'Animation', Field.DWORD)
    if animation_field and animation_field.value > 65535:
        raise ValueError("Animation ID out of range")

🔍 トラブルシューティング

一般的な問題と解決策

❌ StrRef解決の失敗

問題: text_strref が null または無効

解決: TLKファイルの存在確認、StrRefの有効性チェック

⚠️ スクリプト参照エラー

問題: Script フィールドが空または無効

解決: スクリプトファイルの存在確認、デフォルト値設定

🔄 循環参照の検出

def detect_circular_reference(entries, visited=None):
    if visited is None:
        visited = set()
    
    for entry in entries:
        if entry['node_id'] in visited:
            return True
        visited.add(entry['node_id'])
        # 再帰的にチェック

🐛 デバッグ支援

def debug_dlg_structure(gff_data, max_depth=3):
    """DLG構造をデバッグ出力"""
    def print_field(field, depth=0):
        if depth > max_depth:
            return
        
        indent = "  " * depth
        print(f"{indent}{field.label}: {field.name}")
        
        if hasattr(field, 'value') and hasattr(field.value, '__iter__'):
            for sub_field in field.value:
                print_field(sub_field, depth + 1)
    
    print_field(gff_data.root)

🔗 関連記事

基本的な構造理解については、NWN2:EE DLGファイル構造解析 - 基礎編をご覧ください。

最終更新: 2025年7月26日
バージョン: 1.0
対象読者: 開発者・システム実装者

0 件のコメント:

コメントを投稿

NWN2:EE DLGファイル技術仕様 - 開発者編

⚙️ NWN2:EE DLGファイル技術仕様 - 開発者編 開発者・システム実装者 向けのNWN2:EE DLGファイルの詳細技術仕様書です。 📋 目次 GFFファイル形式詳細 フィールド仕様 スクリプトシステム 条件分岐システム カメラシステム 実装...