SkyUI MCM

SkyUI MCMのチュートリアル



Quick Start(SkyUI公式チュートリアル)
https://github.com/schlangster/skyui/wiki/MCM-Quickstart

API Reference(SkyUI公式レファレンス)
https://github.com/schlangster/skyui/wiki/MCM-API-Reference


イントロダクション

Mod Configuration Menu (MCM)は名前の通りModの調整メニューを追加します。
これは自分自身でModのメニューをとりあえず作れるようになるためのチュートリアルです。
ある程度Papyrusに触ったことがある方向けです。最低限CK wikiのスクリプトチュートリアルは済ませましょう。

準備

SkyUI wikiからSkyUI SDKを入れます。
この解説はSkyUI SDK 3.1時のものです。基本的な流れは変わりません。
ダウンロードしたファイルを解凍してScriptフォルダをDataフォルダに入れます。
そしてSkyUI本体も入れておきます。

あなたのModのespをCKで開いてから、Object WindowからQuest項目を選びます。
右クリックしてNewを選択し新しくクエストを作ります。
Quest DataタブでIDを入力(例: aaaxxMCMQuest)。
Start Game Enabledはチェック、Run at onceはチェックを外す。
一旦OK押して閉じます。

再度作成したクエストを開いて、Quest Aliasタブを開きます。
右クリックしてNew Reference Aliasを選びます。
左上AliasにAliasの名前を入力(例:MCMPlayerAlias)
Fill TypeをSpecific Referenceを選んで、Select Forced Referenceボタンを押します。
cellは(any)、RefはPlayerRef('Player')です。

次に画面右側Scripts欄の Addボタン を押します。
Filterにskiとうって検索を絞りSKI_PlayerLoadGameAliasを選びます。
これでAliasは終了ですのでAliasのウィンドウをOKして閉じます。

Scriptsタブを開いてAddボタンを押します。
newscriptを選んで、新しく名前をつけ(例:aaaxxMCMScript)、{Extendsを
ski_configbase}にしてOKを押します。
スクリプトのウィンドウを一旦閉じて、Propertiesボタンを押します。
ModNameを選択してEdit Value。
ここにMod名を記載します。(例:Test)
これで準備は整いました。
後は新しく作ったスクリプトに記述していきます。

MCMの構造と流れ

構造と流れさえ分かればそこまで難しくないです。


細かいことはさておき、手を動かしてみましょう。

Scriptname aaaxxMCMScript extends  ski_configbase
;変数の定義
int ToggleTestID
bool bToggleTest = true
;ページの設定
Event OnPageReset(string page)
   ToggleTestID = AddToggleOption("Test Toggle", bToggleTest)
endEvent

int function GetVersion()
	return 1
endFunction

;選択時の設定
Event OnOptionSelect(int option)
   if (option == ToggleTestID)
       bToggleTest = !bToggleTest
       SetToggleOptionValue(ToggleTestID, bToggleTest)
       If(bToggleTest)
;        bToggleTestがtrueなら グローバル変数.SetValue(1)
       Else
;        bToggleTestがそれ以外(false)なら グローバル変数.SetValue(0)
       EndIf
   endIf
endEvent

;デフォルトの設定(Fキー押した時に呼び出されるイベント)
Event OnOptionDefault(int option)
  If(option == ToggleTestID)
      if (!bToggleTest)
bToggleTest = true
SetToggleOptionValue(ToggleTestID, bToggleTest)
;         グローバル変数.SetValue(1)
endif
  EndIf
EndEvent

;カーソルが乗った時に下に出るテキストの設定
Event OnOptionHighlight(int option)
  If(option == ToggleTestID)
       if (!bToggleTest)
           SetInfoText("Toggle this option on to activate the mod.")
       else
           SetInfoText("Toggle this option off to deactivate the mod.")
       endif
  EndIf
EndEvent

スクリプトを書いたらコンパイルしてからespを保存し、espをアクティブにして実際にゲーム内で確認してみましょう。

Escキーでメニューを開いて、システムタブのMod Configurationです。
例のとおりですとtestという項目があるのでそれを開いて確認してください。
ToggleTestを押しても実際には何にも効果がないのですが、とりあえずは表示できて動かせたと思います。

変数の定義(IDとMCM内の変数の2つ)
OnPageResetにID = Add~Option()を書く
Event OnOption~()内にif option == ID
Set~OptionValue(ID,変数)でMCM上の数値をセットし、グローバル変数か何かで変更した値を渡す。

というのが基本的な流れです。


実際に動くメニューを作る

以下の機能を実装したいと思います。
  • 時間変更をするスライダー
  • 天候を晴れにする機能のキー設定変更
  • キルムーブのOn/Off
  • キルムーブの確率

まず、天候機能を作ります。
Miscellanneous->Globalで右クリックしてNew、aaaWeatherKeyを作ります。
Short, Valueは199。

先ほどのメニューのクエスト(aaaxxMCMQuest)をDepulicateしてaaaWeatherQuestにします。

クエストのスクリプトを削除して新しくスクリプト(aaaxxWeatherScript)を作ります。

Scriptname aaaxxWeatherScript extends Quest  

int WeatherKey
GlobalVariable property aaaWeatherKey auto
Weather property SkyrimClear auto

int function GetVersion()
	   return 1
endFunction 

Event OnInit()
   RegisterKey()
EndEvent

Function RegisterKey()
   UnregisterForKey(WeatherKey)
   WeatherKey = aaaWeatherKey.GetValueInt()
   RegisterForKey(WeatherKey)
EndFunction

Event OnKeyDown(Int KeyCode)
   if (KeyCode == WeatherKey)
       SkyrimClear.ForceActive()
   endif
EndEvent

Property の設定を忘れないように。Auto-Fill Allで全部埋まります。


次にQuest Aliasタブを開いて、プレイヤーのAliasを開きます。
SKI_PlayerLoadGameAliasを削除して新しくスクリプトを作ります。


Scriptname aaaxxTestAliasScript extends ReferenceAlias  

aaaxxWeatherScript Property QuestScript Auto

Event OnPlayerLoadGame()
   QuestScript.RegisterKey()
EndEvent

ロード時に登録したキーが消えるバグがあるので、OnPlayerLoadGame()でロード度にキーを登録し直します。aaaxxWeatherScriptのプロパティの登録を忘れずに。

天気の機能はコレで終わりです。
あとはMCMのスクリプトを書くだけです。
コードが長いけどもめげないこと。

Scriptname aaaxxMCMScript extends  ski_configbase

;プロパティ
aaaxxWeatherScript Property QuestScript Auto
GlobalVariable Property KillMove auto
GlobalVariable Property KillMoveRandom auto
GlobalVariable Property GameHour auto
GlobalVariable Property aaaWeatherKey auto

;変数の定義
int KillMoveActiveID
int KillMoveRandomID
int GameHourID
int WeatherKeyID

bool    _KillMoveActive        = true
float _KillMoveRandom    = 50.0
float _GameHour           = 8.0
int     _WeatherKey           = 199    ;home key
;このMCMのバージョン
int function GetVersion()
	   return 1
endFunction 

;ページの設定
Event OnPageReset(string page)
   SetCursorFillMode(TOP_TO_BOTTOM)
   AddHeaderOption("KillMove")
   KillMoveActiveID = AddToggleOption("KillMove", _KillMoveActive)
   KillMoveRandomID = AddSliderOption("KillMove Random", _KillMoveRandom, "Percent:{0}")
   AddHeaderOption("Time")
   GameHourID     = AddSliderOption("GameHour", _GameHour, "Hour:{0}")
   AddHeaderOption("KeyConfig")
   WeatherKeyID     = AddKeyMapOption("WeatherKey", _WeatherKey)
endEvent

;選択時の設定
Event OnOptionSelect(int option)
  if (option == KillMoveActiveID)
      _KillMoveActive = !_KillMoveActive
      SetToggleOptionValue(KillMoveActiveID, _KillMoveActive)
      If(_KillMoveActive)
       KillMove.SetValue(1)
      Else
       KillMove.SetValue(0)
      EndIf
  endIf
endEvent

;スライダー開いた時のイベント・設定
Event OnOptionSliderOpen(int option)
   if (option == KillMoveRandomID)
       SetSliderDialogStartValue(_KillMoveRandom)
       SetSliderDialogDefaultValue(50)
       SetSliderDialogRange(0, 100)
       SetSliderDialogInterval(1)
   elseif (option == GameHourID)
       SetSliderDialogStartValue(_GameHour)
       SetSliderDialogDefaultValue(8)
       SetSliderDialogRange(0, 24)
       SetSliderDialogInterval(1)
   endIf
EndEvent

Event OnOptionSliderAccept(int option, float value)
   if (option == KillMoveRandomID)
       _KillMoveRandom = value
       SetSliderOptionValue(KillMoveRandomID, _KillMoveRandom, "Percent: {0}")
       KillMoveRandom.SetValue(_KillMoveRandom)
   elseif (option == GameHourID)
       _GameHour = value
       SetSliderOptionValue(GameHourID, _GameHour, "Hour: {0}")
       GameHour.SetValue(_GameHour)
   endIf
EndEvent

Event OnOptionKeyMapChange(int option, int keyCode, string conflictControl, string conflictName)
   if (option == WeatherKeyID)
      _WeatherKey = keyCode
      SetKeyMapOptionValue(WeatherKeyID, _WeatherKey)
      aaaWeatherKey.SetValue(_WeatherKey)
      QuestScript.RegisterKey()    ;キーの再登録が必要
   endIf
EndEvent

;デフォルトの設定(Fキー押した時の挙動)
Event OnOptionDefault(int option)
 If(option == KillMoveActiveID)
   if (!_KillMoveActive)
       _KillMoveActive = true
       SetToggleOptionValue(KillMoveActiveID, _KillMoveActive)
           KillMove.SetValue(1)
   endif
 ElseIf(option == KillMoveRandomID)
       _KillMoveRandom = 50
       SetSliderOptionValue(KillMoveRandomID, _KillMoveRandom, "Percent: {0}")
       KillMoveRandom.SetValue(_KillMoveRandom)
 ElseIf(option == GameHourID)
       _GameHour = 8
       SetSliderOptionValue(GameHourID, _GameHour, "Hour: {0}")
       GameHour.SetValue(_GameHour)
 ElseIf(option == WeatherKeyID)
       _WeatherKey = 199
       SetKeyMapOptionValue(WeatherKeyID, _WeatherKey)
       aaaWeatherKey.SetValue(_WeatherKey)
 EndIf
EndEvent

;カーソルが乗った時に下に出るテキストの設定
Event OnOptionHighlight(int option)
 If(option == KillMoveActiveID)
      if (!_KillMoveActive)
          SetInfoText("Toggle this option on to activate killmove.")
      else
          SetInfoText("Toggle this option off to deactivate killmove.")
      endif
 Elseif(option == KillMoveRandomID)
   SetInfoText("Killmove random percent.")
 Elseif(option == GameHourID)
   SetInfoText("Set game hour.")
 Elseif(option == WeatherKeyID)
   SetInfoText("Set Weather Key.")
 EndIf
EndEvent

例のごとくプロパティ登録を忘れずに。

注意すべき点は1スクリプトにつき、同一のイベントは一つまでなので、 イベント内でif (option == ID)で振り分けます。


作ったMCMを更新するとき

int function GetVersion()
   return 2
endFunction 
returnのところの数値を整数で一つ上げます。ここの数値が変わったタイミングでOnUpdateVersion()のイベントが動くので、ここに追加項目(初期設定だとOnInit()に書く内容)を記載します。
例はキーとリストの追加。
Event OnUpdateVersion()
   DodgeKey = Input.GetMappedKey("Sprint")
   SetKeyMapOptionValue(keyID, DodgeKey)
   InputMethodList = new string[3]
   InputMethodList[0] = "DodgeKey/2Tap"
   InputMethodList[1] = "DodgeKey"
   InputMethodList[2] = "GamePad/2Tap"
EndEvent




添付ファイル