「SKSE上でのデータのセーブ/ロード」の編集履歴(バックアップ)一覧に戻る
SKSE上でのデータのセーブ/ロード - (2018/09/07 (金) 20:25:48) のソース
#contents *目的 SKSEプラグインを用いてデータの保存を行えるサンプルを提供します。 SKSEプラグイン上で処理するデータは、静的変数を用いればゲーム中は値を保持し続けますが、ゲーム終了時にはすべて破棄されます。 このため本来はセーブデータにデータを保存する([[Tips参照>https://www50.atwiki.jp/skyrim_mod/pages/18.html#id_717ea3ed]])必要がありますが、このページのサンプルによりSKSEプラグイン上でデータの保存が可能となりPapyrus上の変数などに戻すような手間が不要になります。 *前提 [[SKSE64プラグイン開発環境構築手順]]にて、skse 本体のコンパイルができる状態にあることが前提となります。 プラグインのサンプルプロジェクトである samplePlugin を元にデータのセーブ/ロードを実装します。 *手順概要 データの保存のために、SKSESelrializationInterfaceクラスが提供されています。これを利用してデータのセーブ/ロードを実現します。 以下の手順によって実装します。 +SKSESerizalizationIntarfaceのインスタンス化 --自分のSKSEプラグインでSKSESerializationInterfaceを利用できるようにします。 +セーブ/ロード時のコールバック関数の作成と登録 --セーブ時及びロード時に動作させる関数を作成し、実際に呼び出されるよう登録します。 +セーブ用関数の実装 --SKSEプラグイン内の変数の値を保存する処理を実装します +ロード用関数の実装 --SKSEプラグイン内の変数へ値を読み込ませる処理を実装します *手順詳細 以下の手順はすべてsamplePluginプロジェクトのmain.cppに対して行います。 **SKSESerializationInterfaceのインスタンス化 グローバル変数としてSKSESerializationInterfaceのポインタを作成します。 IDebugLog gLog; UInt32 g_skseVersion; PluginHandle g_pluginHandle = kPluginHandle_Invalid; SKSEMessagingInterface * g_messaging = nullptr; //*************SKSESerializationIntarfaceポインタ作成************* SKSESerializationInterface * g_serialization = NULL; void SKSEMessageHandler(SKSEMessagingInterface::Message* msg) // ...以下省略... &br() 宣言したg_serialization変数をSKSEPlugin_Query関数の実行時にインスタンス化させます。 extern "C" { bool SKSEPlugin_Query(const SKSEInterface * skse, PluginInfo * info) // ...前半省略... g_messaging = (SKSEMessagingInterface *)skse->QueryInterface(kInterface_Messaging); if (!g_messaging) { return false; } /*************追加部分*************/ // get the serialization interface and query its version g_serialization = (SKSESerializationInterface *)skse->QueryInterface(kInterface_Serialization); if (!g_serialization) { _MESSAGE("couldn't get serialization interface"); return false; } if (g_serialization->version < SKSESerializationInterface::kVersion) { _MESSAGE("serialization interface too old (%d expected %d)", g_serialization->version, SKSESerializationInterface::kVersion); return false; } /*************追加部分*************/ return true; } **セーブ/ロード時のコールバック関数の作成と登録 セーブ/ロード時に実行させるための関数を実装します。 void Serialization_Save(SKSESerializationInterface * intfc) { } void Serialization_Load(SKSESerializationInterface * intfc) { } extern C { // ...以下省略... &br() 上記二つの関数を、SKSESerializationInterface(g_seriarization変数)に登録し、実際にセーブやロードを実行した際に呼び出されるようにします。 この処理は SKSEPlugin_Load内に実装します。 -ここで最初に実行しているSetUniqueIDメソッドですが、第二引数の文字列がプラグインの識別子として動作し、異なるSKSEプラグイン間でのデータの誤ったロードを防ぐようになっていると思われます(''未確認'') -サンプルでは'TEST'としていますが、自作のMODで実装する際は異なる単語にした方が良いです。 bool SKSEPlugin_Load(const SKSEInterface * skse) { if (g_messaging) { g_messaging->RegisterListener(g_pluginHandle, "SKSE", SKSEMessageHandler); } /*************追加部分*************/ // ### this must be a UNIQUE ID, change this and email me the ID so I can let you know if someone else has already taken it g_serialization->SetUniqueID(g_pluginHandle, 'TEST'); g_serialization->SetSaveCallback(g_pluginHandle, Serialization_Save); g_serialization->SetLoadCallback(g_pluginHandle, Serialization_Load); /*************追加部分*************/ return true; } **セーブ用関数の実装 セーブ用関数Serialization_Save上でセーブ処理を実装します。 セーブ処理には引数として受け取るintfcの、以下の2つのメソッドを利用します。 |OpenRecord|SKSEプラグイン内で保存するデータの住み分けやプラグイン更新時の古いデータとの整合性保持を行う| |WriteRecordData|変数に格納されたデータを実際に保存する| &br() 実装サンプルは以下のようになります。ここではtestInt変数内の「64」という数字を保存しています。 const UInt32 kSerializationDataVersion = 1; // グローバルで宣言 void Serialization_Save(SKSESerializationInterface * intfc) { _MESSAGE("save"); SInt32 testInt = 64; if (intfc->OpenRecord('DATA', kSerializationDataVersion)) { intfc->WriteRecordData(&testInt, sizeof(testInt)); } } -OpenRecordメソッドは、以降にWriteRecordDataにより保存するデータに対して識別子とバージョン情報を付与します。 |第一引数|識別子。文字列を登録する。| |第二引数|バージョン情報。ロード時にも用いるためグローバル変数を利用することを推奨。| &br() -WriteRecordDataメソッドにより、変数内の値を保存します。 |第一引数|保存する値を格納した変数のポインタ| |第二引数|第一引数の変数のサイズ| **ロード用関数の実装 *Tips **保存するデータの型について **セーブ/ロードするデータの順序 **LE版Skyrimでの実装について