2018/06/29

UIExtentions リストメニューの実装方法

ユーザーメイドのModが許されているゲームで、どれだけ斬新なModが登場するかは(1)モーションを自由に作れるかどうか(2)UIを自由にカスタマイズできるかどうか、の2点にかかっているんじゃないかと思う今日この頃です。
スカイリムでは、モーションの壁についてはFNISという偉大なModが早々に制約をぶち破り、発売から7年が経過した今では、プロの犯行かと思われるような秀逸なアニメーションが溢れかえっていますが(でも釣りモーションは探せども無いです。誰か作って!)、残念ながらUIの方面については、二、三年前から進化が止まっているように思います。
いい加減、SkyUIのMCMと覇権を競うくらいの新たなUIのフレームワークが出てきても良さそうなものだと思うのですが……いまだにMCM一択というのが残念でなりません。
また、メニュー追加系のUIでは、RaceMenuやEFFの作者さまがお作りになったUIExtensionsがよく使われているなあという印象です。こちらは特にリストメニューがよくできているので、Modderに好まれるのもさもあらん、という感じ。

これはスカイリムのデフォルトのリストメニュー(Message Box)
デフォルトのUIのリストメニューの致命的な欠点は、選択肢が横並びなところです。
横並びだとスペースの都合上、選択肢の個数が限られてしまうし、選択肢の内容も長いテキストは使えません(日本語のような全角文字だとますますつらい)。
デフォルトのメニューの利点ですが、唯一上げるとするなら、本体がMessageというオブジェクトなので選択肢のテキストがローカライズしやすい、という点でしょうか。
しかしそのせいでスクリプトだけでは完結しない(選択肢をCK上で追加しなくてはならない)ので、そこが不便といえば不便です。

ちなみにリストメニューを追加するUI Modとしては、SkyUIの作者さま作の「SkyUILib」についても、私としてはお勧めしたいところです。
字幕ModもDirectorもかな入力メニューも、私はこのModのソースを見ることができたから、Flashファイルの中身まで全部公開してくださっていたから作ることができました。
そんなわけで私にとっては師匠ともいうべき存在なので、ついでに紹介させていただきます。
SkyUILibのリストメニューはデフォルトのメニューの横並び状態を
縦並びにしただけのシンプルな作りです。
SkyUILibのリストメニューの利点としては、バニラのデフォルトのメニューと同様に、メニューの上にタイトル的な一文を追加できるという点がポイントです。
UIExtentionsのリストメニューだと選択肢オンリーなんで、「○○○について選んでください」というような補足説明が表示できないんですよね。
スクリプトもSkyUILibはバニラのMessageの「show()」と同じ感覚で使えます。

ところでスカイリムでは、こういったUI追加Modの実装方法を解説したドキュメントやチュートリアルのようなものって、全くといって良いほど見かけないですね。
汎用のMCMの実装方法については、作者様が自らGitHubのWikiにまとめてくださってますけど、SkyUILibもUIExtentionsも「ソースを見て察しろ」という状態です。
Modderの皆さんはどうやって使い方を会得してるんでしょうか。
皆さん、このくらいは説明なんかなくったって楽勝だろ、というレベルなのでしょうか。
少なくとも私は全然わかりませんでした……特にUIExtentionsは。さっぱり。

そんなわけで手探りで解読したUIExtentionsのリストメニューの実装方法を書いておきます。
■UIExtentionsのリストメニューの実装方法
UIExtentionsのリストメニューの最大の特長は、選択肢にさらに子の選択肢を簡単に追加していけるところです。この子選択肢の機能があるからこそ、多くのModで採用されているのではないかと思います。
UIExtentionsはフレームワークのスクリプトだけでなくUI自体のクライアントとなるespが独立して存在していますので、前提必須ModとしてUIExtentionsを導入した上で、下記のようにして自作Modの任意のスクリプト内でUIExtentionsのリストメニューを読み込みます。
UIListMenu listMenu = UIExtensions.GetMenu("UIListMenu") as UIListMenu
これでUIExtentionsのリストメニューを読み込んだ「listMenu」に関して、「UIListMenu.psc」の関数がなんでも使えるという寸法です。
というてもリストを用意するには「AddEntryItem」という関数さえ知っていればOKです。

たとえばこんな感じの構造のリストメニューを作りたいとします。
最初に「メインメニュー1」「メインメニュー2」「メインメニュー3」の3つの選択肢があって、そのうちの「メインメニュー2」「メインメニュー3」からはさらに分岐する。
「メインメニュー3」のサブメニューの2からは、さらに子の選択肢が3つ派生する。

このような構造のリストの作りたい時はこういう記述になります。
エディタのスクショ画像を貼ったので少し見ずらいですが。
でも「AddEntryItem」という関数だけで指定できてしまっているのが分かりますでしょうか。

「AddEntryItem」という関数で選択肢を追加すると、追加した選択肢は追加した順に0から通し番号が振られます。
(「AddEntryItem」関数の戻り値として取得することができます)
その番号を「entryParent」や「entryCallback」といった引数の値に使うことで、選択肢の分岐を指定するのです。
「entryParent」は自分の親の選択肢の番号、「entryCallback」はおそらく最初の分岐の根元の選択肢の番号です。また子の選択肢を持つ選択肢については「entryHasChildren」の値を「true」にしてあげます。
上記のサンプルではわかりやすいように選択肢のテキストを直接ぶちこんで個別に記述していますが、もちろんstringの配列でwhileなどを使ってまとめて記述してOKです。

選択肢の準備ができたら、あとは「OpenMenu()」関数でメニューを開き、選ばれた選択肢の情報を取得します。
「GetResultInt」で選んだ選択肢の通し番号が分かります。
また「GetResultString」で選んだ選択肢のテキスト自体も取得できます。

こうして書くと、結構単純な作りなのですが……何も説明がないので、どういうしくみなのか解読するのにえらい時間がかかりました。
せめてソースにコメントくらい書いておいて欲しいです。

2018/06/25

SexLab環境のCTD対策

CTDしまくりだったマイエロイリム環境が、試行錯誤の末ようやく安定してきたので週末は純粋にプレイを楽しむことができました。
ウィンターホールド魔法大学をより大学らしくするImmersive College of Winterholdと、ウィンターホールドの町を再建するQaxe's Winterhold Rebuildを入れてみたのですが、本命のSkyrim Romanceはそっちのけで大学生活を満喫しています。
これらのModを入れたからといって魔法大学のクエストに変更があるわけではないのですが、魔法系のスキルを学べる施設が充実したり、先生はより先生らしく生徒たちはより生徒らしく演出されていて、学生としての疑似体験プレイがはかどります。

幻想的な温室のルストラトリウム。
そういえば魔法大学にはスプラウト先生みたいな薬草学の講師っていませんね。
キナレス聖堂みたいなコレット先生のお部屋。
先生方の私室も個性に合わせて飾り付けされてて素敵です。
ちなみに最初はSexLab抜きでプレイしていたのですが、真面目に大学の先生たちにお金払って訓練受けようと思ったら、金策に困ってしまって結局SSLを入れるはめになりました。
何のModが変更しているのか不明なんですが、私の今の環境では薪割りで荒稼ぎができないのです(薪1本1Gにしかならない…)頼みの錬金術もやはり何かのModのせいで(たぶんComplete Alchemy and Cooking Overhaulだと思う)まったくお金にならない。
安易に売春に頼るのはどうかと思うんですが、その辺は自作でリスクを追加しているので、金稼ぎの手段としては我ながらちょうどよいバランスになっているのではないかと思います。
そんなわけでSexLabを入れてもCTDしない安定した環境構築というのが何をおいても大事なわけなんですが、いろいろ試行錯誤した結果、一番効果があったのは下記の2点でした。
(あくまで私のボロいPC環境で、の話です)

(1)必要のない時は「Creature Framework」のCloak rateを「0(無効)」にする。
最初は「Creature Framework」のMod自体のインストールを止めていたんですが、てんこもりのクリーチャーアニメがもったいないので、Modは導入しておいて、必要な時だけ機能をオンにすることにしました。
よくよくMCMの説明を読んでみたら、Performanceの「Cloak rate」を0にすればCreature Frameworkの機能は無効になるのですね。(set to 0 to disable entirelyって書いてある)
確かにここを0に設定すると、クリーチャーにちんちんを付けるスクリプトが全く配られず、ダッシュで屋外のフィールドを駆けまくってもCTDしないようになりました。
ちなみにクリーチャーとのSexを楽しみたい時は、Cloak rateを元の数値に戻すだけでOK。
Creature Frameworkを改めてリビルドする必要もなく、設定した秒数後にはスクリプトがその場のクリーチャーに自動的に配られ、ちんちんが付くのを確認しました。
昔は普通にインストールしても、クリーチャーにちんちん付かないことはざらにあったのですが、バージョンアップのおかげでしょうか、だいぶ反応が良くなりましたね。

(2)バニラ(デフォルト)の装備やアイテムをリプレイスするModは使わない

これは体感として個人的にかなり効果があったと思うだけで、CTDの原因になっていたという確証はまったく無いのですが、まあ、参考として。
SexLab用の環境にして、ちょくちょく起こるようになったのは、アイテムを表示するメニューを開く際に起こるCTDです。
倒した敵の持ち物を漁るためにインベントリを覗くとCTD。
お店で何かアイテムを買おうとするとCTD。
なんかもうメニューを開くのが怖くなってしまって、倒した敵のインベントリは漁らず、買い物もできるだけしないようにしてたのですが、とても不便で仕方がなくて。
いったい何が原因なんだろうとあれこれModを出し入れして、一番「あれ?めったにCTDしなくなったぞ」と実感したのは、バニラのリプレイス装備一式でした。
妊娠Modを導入する際に、バニラのデフォルトの鎧や服を妊娠対応にするべく「PSVAC pregnancy scalable vanilla armor and clothing」というModを導入していたのですが、これがどうも私の環境には合わなかったみたいで。
こちらを抜くとCTDすることがかなり減ったので、登場率の多いバニラのアイテムを直接差し替えることのリスクを改めて実感しました。
インベントリを覗くだけでCTDって、かなりのストレスです。
これは「なんとなくそう感じる」というだけの感想ですが、3Dの画面表示に関する部分で何かしらの問題が発生した場合のCTD率というのは致命的で、何も言い訳も弁解もなく、即落ちするような気がします。
そういうのはPapyrusのエラーログとか見ても無駄です。
そもそもスクリプト自体が元凶になっているCTDなんてほんの一握りなんじゃないかな。

(1)の「Creature Framework」の場合だって、別にスクリプトが悪いわけじゃなく、スクリプトの発動するタイミングが悪いだけだと思います。
おそらく一気に大量の3Dが読み込まれる瞬間が一番危険で……単品ならさほどの負荷ではないアイテムでも、塵ツモで問題が起きやすくなるんじゃないかと。
バニラのアイテムのテクスチャを高解像度なものに差し替えるのも、3Dの描画のタイミングでメモリを圧迫するのか、CTDの一因になってるような気がします。
(特にインベントリに入るアイテムは要注意)
まあ、私のPC環境が貧しいだけで、リッチな環境ではまったくの無問題という気もしますが。

そろそろPC買い替えようかなと思うんですが……普通、PCを四年以上使っていたら調子の悪いところのひとつやふたつは出てくるものなのに、今のPCはまったくの無問題なので、なかなか思い切って買い替えることができないんですよね。
次のTESが出たらと思っていたけど、まだまだ先のようだし……悩ましいです。

2018/06/20

SexLabのアニメ設定を複数保存したい

SexLabのMCMは項目が多くて設定するのが大変ですが、「再設定&掃除」の「設定を保存する」をクリックするとその設定が保存できることは誰でもご存じかと思います。
その際、アニメーションの有効・無効や強姦、前戯フラグのオン・オフなども一緒に保存されていることはご存じでしょうか。もちろん保存した時にレジストしていたアニメーションに限られますけども、人間・クリーチャー共に現在の状況が保存され、後からその設定を読み込むことで、再び同じフラグ状態にすることができます。
(もちろんレジストされていないアニメに関しては復帰しません)
ちなみにこの時、表情の設定も一緒に上書き保存されてしまうので、私はこのおかげで二年前に愛用していた表情jsonファイルを失いました。表情(Expression)の設定は個別にインポート・エクスポートできる機能がついているのだから、一括保存はやめて欲しかったです。
ああ、昔の表情jsonは会心の出来だったのにな……

それはともかくとして、アニメーションの設定もできれば個別に複数セーブ・ロードができたらよいのになと思う今日この頃です。
そんなわけで今日はSexLabとは別ファイルのjsonに、複数セーブ&ロードできる機能をお試しで作ってみました。
セーブ枠はお試しで3個作ってみましたが多くても10個もあれば十分かと。

↓こんな感じで、各セーブをまたいで利用できる外部jsonファイルとして保存されます。
SexLabのMCMのアニメーション設定を保存する関数をそのままパクったので、特に何の苦労もせず30分くらいでできました。
ちなみにSexLabは設定をエクスポートする時、ゲーム自体もセーブする必要があるんですが、いつも面倒くさいと思っていたので、ゲーム自体のセーブは不要にしました。

個別のModとしてブラッシュアップするか、もしくはDirectorに追加するか……考え中です。
セーブ枠が多いと何を保存したか見分けがつかなくなる可能性があるので、日時かセーブ名を残せる機能を追加してもいいかもしれませんね。