キーが押されたら何かしてみます。色々注意するべき点がありますのでまとめました。
キーコードを調べる
キーを指定するためのキーコードが必要です。直接キーコードを指定することもできますし、MCMであらかじめ設定を作っておくのもいいでしょう。
ゲームに割り当てられているキーを使いたい場合があります。例えばアクティベートボタンやスニークボタンなどです。これらはプレイ環境でかわるので、決め打ちで指定できません。
割り当てられている機能のキーコードはInput.GetMappedKey関数で取得できます。
キーコードを調べる (papyrus)
Int Function GetSneakKey()
; まず自動モードで取得してみる
Int iKeyCode = Input.GetMappedKey("Sneak", 0xFF)
if iKeyCode != -1
return iKeyCode
endif
; ダメだったらゲームパッドモードで
iKeyCode = Input.GetMappedKey("Sneak", 0x02)
if iKeyCode != -1
return iKeyCode
endif
; ダメだったらキーボードモードで
iKeyCode = Input.GetMappedKey("Sneak", 0x00)
if iKeyCode != -1
return iKeyCode
endif
; それでもダメだったらゲームパッドの下ボタンを使う
return 267
EndFunction
このGetMappedKey関数はバカなので、一発では取れないことがあります。
特に、controlmap.txtでキーの組み合わせを設定している場合、この関数では取得できません。この関数は整数を1つだけ返すので、2つのキーコードの組み合わせは返せないからです。
キーが押されたら何かする
キーの入力を判定するのに使うのはOnKeyDown関数とOnKeyUp関数です。とりあえず、Wキーが押されたら何かしてみます。Wのキーコードは17です。
キーが押されたら何かする (papyrus)
Scriptname MyQuest Extends Quest
Event OnInit()
RegisterForKey(17)
EndEvent
Event OnKeyDown(Int aiKeyCode)
Debug.Notification("Wキーが押されました")
EndEvent
これで動きます。使いたいキーをRegisterForKey関数で登録するのがポイントです。
注意するべき点は、キーを押すと何度でもOnKeyDownイベントが発生するので、必要に応じて入力を無効にしたり無視したりすることです。無効にするにはUnregisterForKey関数で登録を解除します。一時的に無視するにはフラグを立てるなどして対応します。
メニューを開いているときは何もしない
キャラクターを動かしているときだけ入力を受け付け、メニューが開いているときは無視するにはUtility.IsInMenuMode関数を使えば判定できます。
メニューモードならキー入力を無視する (papyrus)
Event OnKeyDown(Int aiKeyCode)
if Utility.IsInMenuMode()
Debug.Notification("キーが押されましたが、メニューを開いている最中なので無視します")
return
endif
Debug.Notification("キーが押されました")
EndEvent
キーが押されたらコンテナを開き、コンテナを閉じたら処理の続きをする場合、IsInMenuMode関数を使い、メニューモードにいる間は待ち続けるループを作ります。
メニューモードが終わるのを待つ (papyrus)
Event OnKeyDown(Int aiKeyCode)
Debug.Notification("いまからインベントリを開きます")
Game.GetPlayer().OpenInventory()
while Utility.IsInMenuMode()
Utility.Wait(0.1)
endwhile
Debug.Notification("インベントリが閉じられました")
EndEvent
Wait関数は指定された時間が経過するまで待つという関数です。実は、メニューモードにいる間は時間が進まないので、メニューを閉じるまで永遠に待ち続けます。バニラならWait関数だけでもいいのですが、Skyrim Soulsを入れている環境では、メニューを開いている間も時間が進みます。よってWait関数ではダメで、IsInMenuMode関数を使う必要があります。
長押しを判定する
キーが一定時間押される、いわゆる長押しを判定するには、RegisterForSingleUpdate関数を使います。一定時間後にOnUpdateイベントを発生させて長押しを検出します。
長押しの判定 (papyrus)
Bool IsUpdateRegistered
Event OnKeyDown(Int aiKeyCode)
RegisterForSingleUpdate(1.0) ; 1秒後にOnUpdateイベントを予約
IsUpdateRegistered = true ; 予約したということを覚えておく
EndEvent
Event OnUpdate()
IsUpdateRegistered = false ; 時間がきたのでもう覚えてなくていい
Debug.Notification("キーが長押しされました")
EndEvent
Event OnKeyUp(Int aiKeyCode, Float afHoldTime)
if IsUpdateRegistered ; まだ予約している最中なら
IsUpdateRegistered = false ; 予約したことを忘れる
UnregisterForUpdate() ; OnUpdateイベントの予約を取り消す
endif
EndEvent
注意すべき点が多くあり、時間到達前にキーが離されたときと、時間到達後からキーが離されたときのために、それぞれ処理が必要です。