2017年11月27日

【Papyrus.psc】アクティベート時にイベントを実行する

- Papyrusスクリプトの記憶を記録に残すシリーズその2 -

画像はどんどん使いまわしますよ

シリーズの順番は特に決めていませんが、簡単そうな話題から始めます。まだプロパティとか変数とかは出てきません。

今回は、何かをアクティベートしたときにイベントを実行する方法についてです。


目次

  1. 物体をアクティベートしたときにイベントを起こす
  2. アイテムを取得したときにイベントを起こす
  3. プレイヤーがアクティベートしたときだけ実行する

1. 物体をアクティベートしたときにイベントを起こす

1-1. アクティベーターの設置

スクリプトを使うとしたら、まずはこれが分かりやすいでしょう。鎖を引っ張ると扉が開くという動作をさせるときに使われるものです。

まずは Object Window から WorldObjects > Activator を開きます。そこに属するアクティベーターを、Render Window の中にドラッグ&ドロップすれば設置されます。

例として「WETempActivator」をドラゴンズリーチに配置します。

1-2. スクリプトの追加

配置したアクティベーターをダブルクリックすると Reference が開きます。Scripts タブの「Add」ボタンを押してスクリプトを追加しましょう。

スクリプト選択画面になるので、「new script」を選択します。

分かりやすいスクリプト名をつけて「OK」ボタンを押します。他のMODと被らないような名前にしましょう。

作成したスクリプトを右クリックして「Edit Source」を選択すると、内容を書くことができます。

こうして作成したものは、スクリプトのソースファイルです。"Data\scripts\source" フォルダの中に、拡張子「psc」のファイルとして作成されています。

1-3. アクティベートした際のイベント

アクティベートしたときにイベントを実行するには、コードを追記して以下のようにします。
1行目の Scriptname ~ は既に書かれているはずです。

Scriptname EkaTest extends ObjectReference

Event OnActivate(ObjectReference akActionRef)
    Debug.MessageBox("アクティベートしました。")
EndEvent

Event OnActivate(ObjectReference akActionRef) が、アクティベートしたときに発動させるコードです。
Event ~ で始めたら、必ず EndEvent で終わらせるようにします。

Debug.MessageBox() 関数で、画面の中央にメッセージボックスを出します。
このメッセージボックスは「OK」ボタンしかないものです。選択式のメッセージボックスについては、選択式メッセージボックスの作り方 で書いています。

スクリプトを書いたら「File > Save」を選択します。
すると "Data\scripts" フォルダに、拡張子「pex」のファイルが作成されます。このpexファイルが、ゲーム中に実行されるスクリプト本体です。

ともかくこれで、アクティベートした際にメッセージが表示されるようになりました。espファイルを保存してロードオーダーに加えてから、ドラゴンズリーチに行って確認しましょう。

Papyrus にどういう関数があるのかについては、creationkit.com の Category:Papyrus に書かれています。今回のようなイベントの起点については、ページ上方の「Events」の項目内にあります。

1-4. スニーク状態による分岐

スニーク状態のときに異なる動作をさせることもできます。Event OnActivate の中に分岐を入れます。

Event OnActivate(ObjectReference akActionRef)
    If Game.GetPlayer().IsSneaking() == true
        Debug.MessageBox("スニーク状態です。")
    Else
        Debug.MessageBox("立ち状態です。")
    EndIf
EndEvent

Game.GetPlayer() はプレイヤーを指します。これは良く使います。
そして IsSneaking() でスニーク状態かどうかを取得しています。

If式で真を表すときは「==」と2つ書きます。偽は「!=」です。
「==」や「!=」を表す書き方は他にもあるのですが、個人的にはこれが見やすいので今後も統一して記述します。

目次に戻る


2. アイテムを取得したときにイベントを起こす

2-1. 取得した際のイベント

チーズや武器など、ゲーム内でクロスヘアを合わせたときに「取る」という文字が出るオブジェクトに設定する方法です。

アイテムを普通にアクティベートすると、対象を「取る」ことになってインベントリに入ります。スクリプトの内容はその直後に実行されます。
このとき、原則として「取る」動作をキャンセルすることはできません。

スクリプトの書き方は、アクティベーターのときと同様です。

Event OnActivate(ObjectReference akActionRef)
    Debug.MessageBox("アイテムを取りました。")
EndEvent
2-2. 掴んだ際のイベント

アイテムを掴んで移動させようとしたときに動作させる方法です。掴む動作は OnGrab という別のイベントで管理されます。

;--------------------------------------------------普通にアクティベート
Event OnActivate(ObjectReference akActionRef)
    Debug.MessageBox("アイテムを取りました。")
EndEvent

;--------------------------------------------------掴む
Event OnGrab()
    Self.BlockActivation()
    Debug.MessageBox("アイテムを掴みました。")
    Self.BlockActivation(false)
EndEvent

掴んだことは OnGrab で取得できますが、これでイベントを発動させると、それに続けて普通にアクティベートしてアイテムを取ってしまいます。
そのため、Self.BlockActivation() という行を最初に記述して、アクティベートを防ぐ処理をしています。

OnGrab でやりたいことが終わったら、Self.BlockActivation(false) として元に戻しておきます。そうしないとアクティベートできないアイテムになってしまいます。

目次に戻る


3. プレイヤーがアクティベートしたときだけ実行する

アクティベートしたのがプレイヤーであるかどうかを判定して処理を分岐させることもできます。

Event OnActivate(ObjectReference akActionRef)
    If akActionRef != Game.GetPlayer()
        Return
    EndIf

    Debug.MessageBox("プレイヤーがアクティベートしました。")
EndEvent

Game.GetPlayer() でプレイヤーを取得できますので、akActionRef(アクティベートした人)と同じかどうかで分岐しています。

「!=」はイコールでないという意味ですので、プレイヤーでない場合にIfの分岐に入ります。
Return については深く触れませんが、そこでスクリプトを終了させたいときに使います。

OnActivate の最初にこの分岐を入れ、アクティベートした人がプレイヤーでない場合は即終了します。こうすることで、以降の処理を実行できる人がプレイヤーに限定されます。

目次に戻る


【Papyrus.psc】シリーズリスト

補足:私はスクリプトを書くのは好きですが、専門家ではありません。内容は creationkit.com の情報と個人的な経験を基にして書いています。どうかご参考程度にご覧ください。


0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。