【MCM実装-6】MCM設定を自動で保存する

スクリプトを改変して、設定を自動で保存するようにしてみます。さらに、保存された設定をニューゲームの際に自動で反映させます。

これは SkyUI の標準機能ではないので最後の話題として持ってきました。記述パターンさえ掴めれば、機能を組み込むこと自体はそれほど難しくありません。


1. PapyrusUtil のインストール

1-1. Address Library をインストールする

PapyrusUtil を使うため、まずは前提MODを入れておきます。

1-2. PapyrusUtil をインストールする

PapyrusUtil には外部ファイルの保存機能があり、MCM設定の保存にはそれを利用します。MODを公開するときにも、ユーザーに対して必須MODとして案内しておく必要があります。


2. 外部ファイルへの保存

2-1. 使用するスクリプトの説明を読む

外部ファイルにはJSONという形式を使用します。使う関数は PapyrusUtil の “JsonUtil.psc” というファイルに書いてあります。具体的な使用法については “StorageUtil.psc” と同様のためそちらに書いてあります。

ある程度はこのページで解説しますが、詳細については psc を読んでください。

2-2. 保存機能を実装する

MCMスクリプトに PapyrusUtil の関数を組み込み、JSONへの保存機能を実装します。まずは、トグル項目をアクティベートしたときに設定を保存するようにしてみます。

GlobalVariable Property gloEnabled Auto  ; 機能有効のときは1、無効のときは0に設定

Int oidEnabled  ; Toggle Option の Option ID(OID)を格納する変数
String strConfigFile = "EkaMod-MCM"  ; 保存する設定ファイル名
String strKeyEnabled = "Enabled"  ; JSONに保存されるキーの名称

;--------------------------------------------------
Event OnOptionSelect(Int a_option)  ; アクティベートしたとき
    If a_option == oidEnabled
        Bool booEnabled = True  ; トグルをセットする際に使う変数。
        Int intEnabled = 1  ; 値をセットする際に使う変数。

        If gloEnabled.GetValue() > 0  ; 機能が有効なとき
            booEnabled = False  ; 表示をOFFにするために False にする。
            intEnabled = 0  ; 機能を無効にするために0にする。
        EndIf

        SetToggleOptionValue(a_option, booEnabled)  ; トグル表示を入れ替える。
        gloEnabled.SetValue(intEnabled)  ; 機能を有効にするかどうかを GlobalVariable にセットする。
        JsonUtil.SetIntValue(strConfigFile, strKeyEnabled, intEnabled)  ; 一時データにキーと値をセットする。
    EndIf
EndEvent

JSONファイルへは、識別用のキーとなる文字列と、具体的な値との組み合わせで保存されます。

新しく String 型の変数を2つ作り、strConfigFile に保存ファイル名を、strKeyEnabled に使用するキーの名前を設定しています。

保存するのは20行目の JsonUtil.SetIntValue 関数です。ここの引数にファイル名、キー、値を渡し、一時データとしてセットします。プレイヤーがゲーム中にセーブを行うと、その一時データが実際にJSONに書き出されます。保存先は “Data/SKSE/Plugins/StorageUtilData” です。

2-3. 保存する値の型によって使い分ける

PapyrusUtil がサポートしている型とその関数には、以下のようなものがあります。

  • SetIntValue … Int 型の値を保存する。整数の保存に使用する。
  • SetFloatValue … Float 型の値を保存する。小数点を含む値の保存に使用する。
  • SetStringValue … String 型の値を保存する。文字列の保存に使用する。
  • SetFormValue … Form 型の値を保存する。esp 名、および FormID のロードオーダー部分を抜いた下6桁を保存する。
  • IntListAdd … リストとして Int 型の値を保存する。配列のように、インデックスを使った処理が可能となる。
  • FloatListAdd … リストとして Float 型の値を保存する。
  • StringListAdd … リストとして String 型の値を保存する。
  • FormListAdd … リストとして Form 型の値を保存する。

Form 型では、値が「FormID の下6桁|esp 名」の形式で保存されます。これにより、もし esp のロードオーダーが変更されても正しい Form を取得できるようになっています。

保存できる型は上に挙げた4種類ですが、それを扱う関数はいろいろとあります。”StorageUtil.psc” に書いてある説明を読んで使えそうなものを探すと良いでしょう。

2-4. デフォルトキーを押したときに保存対象から外す

デフォルトキーを押したときにどうするかは、MODによって変わってきます。デフォルト値をJSONに保存することもできるし、保存対象から外すこともできます。

保存対象から外すには UnsetIntValue を使います。

GlobalVariable Property gloEnabled Auto  ; 機能有効のときは1、無効のときは0に設定

Int oidEnabled  ; Toggle Option の Option ID(OID)を格納する変数
String strConfigFile = "EkaMod-MCM"  ; 保存する設定ファイル名
String strKeyEnabled = "Enabled"  ; JSONに保存されるキーの名称

;--------------------------------------------------
Event OnOptionDefault(Int a_option)  ; デフォルトキーを押したとき
    If a_option == oidEnabled
        SetToggleOptionValue(a_option, True)  ; トグル表示をONにする。
        gloEnabled.SetValue(1)  ; 機能を有効にする。
        JsonUtil.UnsetIntValue(strConfigFile, strKeyEnabled)  ; 保存対象から外す。
    EndIf
EndEvent

3. ニューゲームへの反映

3-1. 設定をロードするための関数を作成する

それでは、保存された値をニューゲームに反映してみましょう。まずは保存されたJSONをロードする方法をお示しします。

新しく LoadConfig という関数(Function)を作成し、その関数を呼び出せばJSONをロードして gloEnabled に反映できるようにしておきます。こうすることで、後から反映のタイミングを変えたくなったとき、呼び出す箇所を変えるだけで済みます。将来的に読み込む項目が増え、コードが読みづらくなってしまうのを防ぐ狙いもあります。

GlobalVariable Property gloEnabled Auto  ; 機能有効のときは1、無効のときは0に設定

String strConfigFile = "EkaMod-MCM"  ; 保存する設定ファイル名
String strKeyEnabled = "Enabled"  ; JSONに保存されるキーの名称

;--------------------------------------------------
Function LoadConfig()  ; 設定をロードするタイミングを変更できるように関数化しておく。
    If JsonUtil.IsGood(strConfigFile)  ; 有効な保存ファイルが存在するとき
        Int intEnabled = JsonUtil.GetIntValue(strConfigFile, strKeyEnabled, 1)  ; ファイルの値を読み込む。
        gloEnabled.SetValue(intEnabled)  ; GlobalVariable に反映する。
    EndIf
EndFunction

有効な保存ファイルが存在するかどうかは IsGood を使って調べることができ、これが True のときに読み込む処理を行います。ここの分岐は「If JsonUtil.IsGood(strConfigFile) == True」と書いても同じです。

GetIntValue にファイル名とキーの名前を渡して値を読み込みます。このとき、キーが存在しない場合に返す値を3番目の引数に設定することができますので、必要なら書いておいてください。デフォルトでは0がセットされており、上記のコードでは1にしています。このコードだと、もし保存ファイルの中に “Enabled” というキーが見つからなければ、intEnabled の値は1になって機能が有効化されます。

ここまでのように、独立した項目におけるJSONの操作は Set**Value、Unset**Value、Get**Value の組み合わせで実装できます。

3-2. ニューゲームのときにのみ設定を反映させる

ニューゲームで確実に起こるイベントは OnConfigInit です。このイベントの中で LoadConfig 関数を呼び出せば、保存ファイルから設定を反映させることができます。

ただし、OnConfigInit はスクリプトをバージョンアップした際にも実行されるので、制限を加えて最初の1回だけ反映させるようにします。

Bool Property booLoadConfig = True Auto Hidden  ; 設定をロードするかどうか

;--------------------------------------------------
Event OnVersionUpdate(Int aVersion)  ; バージョンアップを検出
    If aVersion > 1  ; バージョンが2以上のとき
        OnConfigInit()  ; 初期設定をやり直す。
    EndIf
EndEvent

;--------------------------------------------------
Event OnConfigInit()  ; 初期設定
    Pages = new String[1]  ; ページを1つ作成する。Pages プロパティは SKI_ConfigBase によって定義済み。
    Pages[0] = "$General"  ; ページ番号は0から始まる。$ は多言語対応のための文字。

    If booLoadConfig  ; 設定をロードするフラグが True のとき
        booLoadConfig = False  ; 2度とロードしないようにフラグを変更する。
        LoadConfig()  ; 設定をロードする。
    EndIf
EndEvent

booLoadConfig という Bool 型のプロパティを新規に作成し、設定をロードするかどうかのフラグとして使用しています。初期値は True で、ニューゲームの際は分岐の中に入って LoadConfig が実行されます。それ以降はフラグが False になるので、バージョンアップのときには反映されないということになります。

booLoadConfig 宣言文の最後についている Hidden は、CKでスクリプトの Properties ダイアログを開いたときに表示させないための設定です。ダイアログに余計な項目を出さないようにすることで、表示をすっきりさせたりミスを予防したりすることができます。


4. 完成したMCMスクリプトコード

以上で完成となります。このシリーズを通して、MCMが少しずつ出来上がっていく様子をお伝えできていたら嬉しいです。最後までお読みくださり、どうもありがとうございました。

Scriptname EKA_scrMCM extends SKI_ConfigBase

Bool Property booLoadConfig = True Auto Hidden  ; 設定をロードするかどうか
GlobalVariable Property gloEnabled Auto  ; 機能有効のときは1、無効のときは0に設定

Int oidEnabled  ; Toggle Option の Option ID(OID)を格納する変数
String strConfigFile = "EkaMod-MCM"  ; 保存する設定ファイル名
String strKeyEnabled = "Enabled"  ; JSONに保存されるキーの名称

;--------------------------------------------------
Function LoadConfig()  ; 設定をロードするタイミングを変更できるように関数化しておく。
    If JsonUtil.IsGood(strConfigFile)  ; 有効な保存ファイルが存在するとき
        Int intEnabled = JsonUtil.GetIntValue(strConfigFile, strKeyEnabled, 1)  ; ファイルの値を読み込む。
        gloEnabled.SetValue(intEnabled)  ; GlobalVariable に反映する。
    EndIf
EndFunction

;--------------------------------------------------
Int Function GetVersion()  ; バージョン番号の設定
    Return 1  ; 最初は1。このスクリプトをバージョンアップするごとに数値を上げる。
EndFunction

;--------------------------------------------------
Event OnVersionUpdate(Int aVersion)  ; バージョンアップを検出
    If aVersion > 1  ; バージョンが2以上のとき
        OnConfigInit()  ; 初期設定をやり直す。
    EndIf
EndEvent

;--------------------------------------------------
Event OnConfigInit()  ; 初期設定
    Pages = new String[1]  ; ページを1つ作成する。Pages プロパティは SKI_ConfigBase によって定義済み。
    Pages[0] = "$General"  ; ページ番号は0から始まる。$ は多言語対応のための文字。

    If booLoadConfig  ; 設定をロードするフラグが True のとき
        booLoadConfig = False  ; 2度とロードしないようにフラグを変更する。
        LoadConfig()  ; 設定をロードする。
    EndIf
EndEvent

;--------------------------------------------------
Event OnPageReset(String a_page)
    If a_page == ""  ; 初期画面
        LoadCustomContent("EkaMod/Image.dds", 56.0, 43.0)  ; 640×360ピクセル画像の場合
        Return  ; 後で各ページを追記していくため、初期画面の表示処理はここで終わらせておく。
    EndIf

    ;--------------------------------------------------
    UnloadCustomContent()  ; 各ページを表示する前に画像を非表示にする。
    SetCursorFillMode(TOP_TO_BOTTOM)  ; ページ内の項目の配置順。TOP_TO_BOTTOM または LEFT_TO_RIGHT。

    ;--------------------------------------------------
    If a_page == "$General"  ; ページ名で分岐する。
        Bool booEnabled = False  ; トグルの初期値をセットする際に使う変数。

        If gloEnabled.GetValue() > 0  ; 機能が有効なとき
            booEnabled = True  ; トグル表示をONにするために True にする。
        EndIf

        oidEnabled = AddToggleOption("$Enabled", booEnabled)  ; Toggle Option 項目を配置する。
    EndIf
EndEvent

;--------------------------------------------------
Event OnOptionSelect(Int a_option)  ; アクティベートしたとき
    If a_option == oidEnabled
        Bool booEnabled = True  ; トグルをセットする際に使う変数。
        Int intEnabled = 1  ; 値をセットする際に使う変数。

        If gloEnabled.GetValue() > 0  ; 機能が有効なとき
            booEnabled = False  ; 表示をOFFにするために False にする。
            intEnabled = 0  ; 機能を無効にするために0にする。
        EndIf

        SetToggleOptionValue(a_option, booEnabled)  ; トグル表示を入れ替える。
        gloEnabled.SetValue(intEnabled)  ; 機能を有効にするかどうかを GlobalVariable にセットする。
        JsonUtil.SetIntValue(strConfigFile, strKeyEnabled, intEnabled)  ; 一時データにキーと値をセットする。
    EndIf
EndEvent

;--------------------------------------------------
Event OnOptionDefault(Int a_option)  ; デフォルトキーを押したとき
    If a_option == oidEnabled
        SetToggleOptionValue(a_option, True)  ; トグル表示をONにする。
        gloEnabled.SetValue(1)  ; 機能を有効にする。
        JsonUtil.UnsetIntValue(strConfigFile, strKeyEnabled)  ; 保存対象から外す。
    EndIf
EndEvent

;--------------------------------------------------
Event OnOptionHighlight(Int a_option)  ; フォーカスしたとき
    If a_option == oidEnabled
        SetInfoText("$Enabled_info")  ; 説明書きを表示する。内容は翻訳ファイル内に記載する。
    EndIf
EndEvent

【MCM実装 シリーズ】
1. Creation Kit で Papyrus を扱えるようにする
2. MCMに登録するための基本構造を作る
3. 初期画面とページの枠組みを作る
4. ページ内の項目を作る
5. スクリプトMODを配布形式にまとめる
6. MCM設定を自動で保存する

Leave a comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

two × one =