■Unity開発メモ用のWiki◎現在扱っていること・Unity全般・MMDからUnityへの変換してインポート・MMDの仕様把握・BlenderでMMDモデルのカスタム


目次


パピルスの構文

基礎の基礎

基礎知識・雑多

・Skyrimの要素はすべてBaseとReferenceで構成されている
・Baseはクラス定義
・Referenceは生成されたインスタンス

■オブジェクトとは?
各スクリプトは、「Quest」、「Reference」、「Actor」、「Book 」などのObjectのタイプとして定義されます。
ほとんどの場合、これらのスクリプト オブジェクトは、エディタのマスターファイルにあるオブジェクトと正確に関連付けられています。

スクリプトを書く前に、それがどのような種類のスクリプトになるかを考える必要があります。
言い換えれば、どのタイプのオブジェクト上で実行されるかということです。
それを決定したら、.psc ファイルの先頭で宣言して新しいスクリプトを作成し、そのベースとなるオブジェクト スクリプトを拡張します。

■イベントとは?
イベントは、何かが起こったときにゲームが呼び出す特別な関数です。
イベントを定義するだけではゲームがそれを呼び出すわけではないことに注意してください。
ゲームがすでに送信しているイベントの名前と引数リストに従う必要があります。
https://www.creationkit.com/index.php?title=Events

たとえば、アクターが死亡したときにゲームがアクターにアタッチされたアクター スクリプトに送信するOnDeath()イベントがあります。
これにより、プレイヤーが特定の敵を倒した後にクエストを完了するなど、ゲーム イベントに応答することができます。

■pscとpsc
Papyrus スクリプトは、実際に実行される pex というファイルと、そのソースファイルである psc とで構成されている
psc:コンパイル前のファイル
pex:コンパイル後のファイル

◎バニラのスクリプトソース
バニラのソースファイルはすべて “Data/Scripts.zip” に圧縮されている

◎保存場所
pexファイル
“common/Skyrim Special Edition/Data/Scripts”
pscファイル
“common/Skyrim Special Edition/Data/Source/Scripts”

・スクリプトは「Skyrim Special Edition\Data\Scripts\Source」ではなく、
 「Skyrim Special Edition\Data\Source\Scripts」に配置する?
 →昔と今ではディレクトリ構造が変わった?

配列(Array)

多次元配列は許可されません。
◎例
; 整数の配列
int[]
; MyObject の配列
MyObject[]

■配列の作成
配列を作成するには、「new」キーワードに続いて型とサイズを使用します。
サイズは 2 つの角かっこ内の整数で示され、変数にすることはできません。
(つまり、配列サイズはコンパイル時に定義する必要があります)

各要素の初期値は、その型の デフォルト値になります。

配列プロパティを作成する場合、Creation Kit は配列に格納される要素の数によって配列のサイズを決定します。
これは、関数の外のスクリプトでは使用できないことに注意してください。

; 20 個の float の配列を作成します
float[] x = new float[20]
; 5 つの MyScript の配列を作成します
MyScript[] x = new MyScript[5]

■配列の長さ
配列の長さを取得するには、配列を保持する変数の読み取り専用の長さプロパティにアクセスします。
変数が None の場合でも、長さは成功しますが、0 が返されます。
配列内の最後の有効なインデックスは、配列の長さから 1 を引いたものであることに注意してください。

例)
int[] myArray = new int[10]
x = myArray.Length ; x は 10 になります
; 初期化されていない配列の長さを取得します (なし) 
float[] myArray
x = myArray.Length ;; x は 0 を取得します

■配列要素
特定の配列要素を取得するには、必要な要素のインデックスを 2 つの角括弧の間に入れるだけです。
この値は、式、関数の戻り値、またはその他のものから取得することもできます
(例外については、以下の警告を参照してください)。
配列内の有効な要素は、0 から長さから 1 を引いた値までです。

例)
; 配列の最初の要素を取得
x = myArray[0]
; 配列の最後の要素を取得します
x = myArray[myArray.Length - 1]

基本的な構文(関数・ライブラリ)

◎ライブラリとは?
ライブラリ≒ゲーム側作ったでまとまった関数リスト
例えばGameはゲーム全般に関わるライブラリ
実際のこのリストの場所はData\Scripts\Source\Game.pscにある

◎実際にライブラリを使うには?
スクリプトで「Game」ライブラリにある「GetPlayer()」関数を使う場合、頭に「Game.」を付ける
 →「.」は単に区切りで「、」みたいなもの

SKSEはこの関数とイベントのリスト(ライブラリ)を大幅に拡張するもの

◎対象があるパターンの構文
〜の.〜を〜する()
対象.実行()
型.関数(引数)

例:
Actor、ObjectReference、Form、Formlistなど

Actor.GetActorValue() 指定したアクターの指定したActorValueの取得
ObjectReferance.Disable() 指定したオブジェクトリファレンスを非表示にする
Form.GetGoldValue() 指定したフォームの金額のベース値の取得

◎対象の指定がないパターンの構文
ライブラリ.〜を〜する()

例:
Game.GetPlayer() プレイヤーをアクター型として取得する。
Utility.Wait(0.5) これの書かれた部分でこのスクリプトの処理を0.5秒待つ。
Debug.notification("Hello world.") 左上にHello worldと通知を出す。
Math.abs(-1.0) 引数の数値を絶対値として返す。つまり結果は1.0。

Utility、Debug、Math、Gameなど。

変数とプロパティ

変数とプロパティは似たもので、どちらも値とオブジェクトを「保持」します。
変数は「プライベート」であり、そのスクリプトのみが変数を認識し、その内容を設定および取得できることを意味します。
プロパティは基本的に他のスクリプトがアクセスできる変数であり、その内容は他のスクリプトによって設定および取得できます。
変数またはプロパティが整数などの数値を保持している場合、get/set でその値を返します。

■プロパティの宣言
スクリプトにはPropertiesを持つこともできます。
これは、他のスクリプトがプロパティを問い合わせて設定できる点を除けば、変数とほぼ同じように機能します。
プロパティはエディターでも変更できます。
データの中身をesp側で保持しています。


自動プロパティ(基本こっちを使っている?)
auto プロパティとは、 get 関数と set 関数をバックグラウンドで作成するプロパティです。

プロパティ定義の最後に「auto」を追加します。
「= <値>」構文を使用してプロパティの初期値を設定できます。
例:
int property myInt = 5 auto

■特殊な変数【Self・Parent】
・「Self」は、関数が実行されているスクリプトのインスタンスを指し、自分自身を
 パラメータとして別の場所にある別の関数に渡したい場合に便利です。
・「Parent」は、親を拡張する場合に、親スクリプトの関数のバージョンを呼び出すためにのみ使用されます。
SomeObject.OtherFunction(self)
Parent.DoStuff()

■変数とプロパティの設定
◎スクリプトでの変数とプロパティの設定
スクリプト自体で 変数に値を割り当てる場合、ある場所で宣言し、別の場所で設定することができます。
;スクリプトの先頭で変数を宣言した
 Int MyStage
  ;...
  MyStage = 100
または、宣言時に割り当てることもできます。
Int MyStage = 100

◎エディターでのプロパティ データの設定
エディターでオブジェクトをポイントするか、エディターに値を入力してプロパティを割り当てる方法です。
これは、前に説明したサンプル スクリプトで MyQuest プロパティと StageToSet プロパティを設定する方法です。

エディターの多くのフォームには「スクリプト タブ」があり、
a) オブジェクトにスクリプトを追加し、
b) それらのスクリプトのプロパティの値を設定できます。

下の画像では、myQuest が MQ101 に設定され、StageToSet が 100 に設定されていることがわかります。

アクティベーターベースオブジェクトのスクリプトプロパティへのアクセス



状態(State)

「状態」とは、異なるバージョンの関数またはイベントを呼び出す スクリプトを設定できるモードです。

◎オートステート
状態の先頭に「Auto」を付けると、スクリプトはその状態で開始されます
( OnBeginStateは送信されません)。
スクリプト内で auto にできる状態は 1 つだけです。
子スクリプトの自動状態は親の自動状態よりも優先されますが、
子に自動状態がない場合は親の自動状態が使用されます。

◎「空」の状態
状態ブロックの外側で定義された関数またはイベントは、「空の状態」にあると言われます。
これは、スクリプトがどの状態にもない場合、または現在の状態が関数のオーバーライドを実装していない場合に使用される関数のバージョンです。

状態に実装されたすべての関数は、現在のスクリプトまたは親のいずれかで空の状態でも実装される必要があります (同じ名前、戻り値の型、パラメーター リストを使用)。

◎状態の切り替え
スクリプトの状態を切り替えるには、GotoStateを呼び出し、切り替え先の状態の名前を文字列として渡します。
状態は宛先スクリプトに存在する必要はありません。空の状態に切り替えるには、空の文字列を渡します。

◎現在の状態の取得
現在の状態を取得するには、GetStateを呼び出します。現在の状態名を文字列として返します。

◎状態が機能やイベントに与える影響
実行するために選択される関数またはイベントは、次のアルゴリズムによって決定されます。
  1. 関数の現在のスクリプトの状態を確認します。
  2. 関数の親スクリプトの状態を確認します。
  3. 現在のスクリプトの関数の空の状態を確認します。
  4. 関数の親スクリプトの状態を確認します。

Condition Functions(条件関数)まとめ

Spell,Magic Effect, PackageやPerk等の様々なところにでてくるConditionとは条件文です。
この条件にあったら効果が発動します。

Conditionのチェックは一回たびに発動し、その負荷はスクリプトの関数と同等の重さです。

◎ANDとORについて
ANDとORは常にその行のあとにしか影響しません。

セリフや魔法、パークなどの条件設定であるConditionのまとめ
逆引きCondition Functions:https://catwalkers.blog.fc2.com/blog-entry-49.html
Condition Functions:https://catwalkers.blog.fc2.com/blog-entry-50.html

■[Condition Function 一覧]
◎アクターの基本情報関連

◎犯罪関連
[

◎戦闘関連

◎AI関連

◎派閥

◎オブジェクト関連

◎アニメーション関連

◎場所

パピルスの基礎知識

フォームID(FormID)・フォームリスト(FormList)とは?

CK上のオブジェクト=フォーム(Form)です。
オブジェクトリファレンス=実ゲーム内においてあるもの
Form ID ≒ アドレス
Form ID(アドレス)とEditor IDは、同じ物が無いユニークなもの。

■フォーム・フォームリストに関する仕様(UESP)
◎Form Script
https://ck.uesp.net/wiki/Form_Script
◎FormList Script
https://ck.uesp.net/wiki/FormList_Script

■フォームの取得関連のスクリプト
参考:【Papyrus.psc】Int型やString型のRefIDを取得・表示する
https://skyrimfromnow.blogspot.com/2019/09/papyrus...
◎Form.GetFormID()
・Form や ObjectReference のIDを Int型 で取得する。
◎Game.GetForm(int aiFormID)
・aiFormID (Int型) から Form を取得する。
◎Game.GetFormFromFile(int aiFormID, string asFilename)
・asFilename (String型) のesp名のロードオーダーを aiFormID に付与した上で Form を取得する。

■フォームリスト(FormList)とは何か?
参考: GECK Wiki
https://geckwiki.com/index.php?title=FormList

■フォームリスト(FormList)を配列の様に使う
参考:https://geckwiki.com/index.php?title=How_to_Keep_T...

フォームとフォームリスト

◎フォームとフォームリストに関するメモ
・CK→オブジェクトウィンドウ「Miscellaneus」→「FormList」
・フォーム→CKでのオブジェクトのセル、データベース的?
・フォームリスト→フォームの配列?一覧?
 →フォームリストはOutifitリストの様に使える
 →フォームリストは入れ子構造に出来る
 →フォームリストには、防具、アイテム、アクター等を入れることが出来る?


◎xEdit・スクリプト・ゲーム画面でのフォームリストの関係

xEditでフォームリストの並び替えを行う

スクリプトの拡張(Extending Scripts)とは

◎概要
・スクリプトの拡張とは、元のスクリプトを編集せずに、ほぼ目的の処理を実行するスクリプトを取得し、
 そのイベントまたは関数の一部を変更して別の処理を実行する行為です。
 →C系で言うクラスの継承?

◎用語
親(Parent)拡張されているオリジナルのスクリプト。
子(Child)親を拡張するスクリプト
継承(Inherit)子スクリプトが変更せずに親から何かを取得すると、それらを「継承」します。
オーバーライド(Override)子スクリプトが新しいバージョンを作成して親の動作を変更すると、
親のバージョンが「オーバーライド」されます。

◎拡張の仕方
・スクリプトの先頭の「scriptname x」の後に「extends y」を追加します。
・Y は拡張するスクリプトの名前です。
例:
Scriptname SpikeTrap extends Trap
この場合、「SpikeTrap」スクリプトは「Trap」スクリプトを拡張しています。

■拡張スクリプトでできること・機能とイベント
・子スクリプトは、親のすべての関数とイベントにアクセスできます。
・子スクリプトで実装していない関数やイベントは、子スクリプトに継承されます。
・関数またはイベントが親に実装されており、それを子にも実装すると、子が親をオーバーライドし、
 その関数またはイベントへの呼び出しでは代わりに子のバージョンが使用されます。
・子に関数またはイベントを実装するときは、名前とともにパラメーターと戻り値の型を
 一致させる必要があることに注意してください。そうしないと、スクリプトはコンパイルされません。

他のスクリプトへのアクセス

他のスクリプトからのプロパティの取得

クエストにアタッチされたスクリプトだけでなく、任意のオブジェクトにアタッチされたスクリプトのプロパティにもアクセスできます。
ただし、特定のオブジェクトにアタッチされた特定のスクリプトにアクセスすることになります。
例:
ScriptName ScriptA extends ObjectReference
 
int Property count Auto
float Property weight Auto

他のスクリプトからの関数へのアクセス

あるスクリプトの関数 (またはプロパティ、状態など) に別のスクリプトからアクセスするには、いくつかの方法があります。
次の例では、ScriptA で作業しているが、ScriptB 内の関数にアクセスする必要があると仮定します。

■方法 1: ターゲット スクリプトを入力プロパティとして設定する
アクセスするスクリプト (ScriptB) を、アクセス元のスクリプト (ScriptA) 内のプロパティとして宣言します。
この方法は、インスタンスが 1 つだけあるスクリプト (特定の Quest または ReferenceAlias にアタッチされたスクリプトなど) にのみアクセスする必要がある場合に最適です。
これは、CK のプロパティを入力するときに、アクセスするスクリプトの特定のインスタンスを選択する必要があるためです。
例:
myRefAliasScriptプロパティrefScript auto       ;CK エディタでこのプロパティにクエストを入力します
 ;... 
refScript 。myRefAliasScriptFunction01 ( ) 
refScript 。myRefAliasScriptFunction02 ( )         ;参照エイリアス スクリプト内の 2 つの関数にアクセスします

■方法 2: オンザフライで変数を作成してターゲット スクリプトにアクセスする
アクセスするターゲット スクリプト (ScriptB) のタイプを持つ変数を宣言します。
次に、その変数を、アクセスする必要がある ScriptB のインスタンスと等しくなるように設定します。
この方法は、次のような場合に最適です。
(1) 区別する必要がある ScriptB のインスタンスが複数あります (たとえば、ScriptB が複数の異なるアクターにアタッチされている)
(2) ScriptB は実行前には存在しないため、プロパティに値を設定することはできません
 (たとえば、ScriptB は、ScriptA PlaceAtMe() によって存在するまで存在しない ObjectReference にアタッチされます)。

他のスクリプトへのアクセスメモ

参考:【Papyrus.psc】オブジェクトに付けたスクリプトの関数やプロパティを呼び出して使う方法
https://skyrimfromnow.blogspot.com/2018/07/papyrus...

◎呼び出し先の関数が記述してあるスクリプト
Scriptname [スクリプトファイル名] extends [このスクリプトを取り付けたオブジェクトの型]
Scriptname My_Script_WheelMenu_Corde extends ReferenceAlias
◎呼び出し元のスクリプト
Scriptname My_Script_WheelMenu extends ReferenceAlias

◎呼び出し先のプロパティを定義する?
[呼び出し元のスクリプトのextends型] Property [スクリプト内で使うプロパティの名前] Auto
ReferenceAlias Property Corde Auto

◎オブジェクトに付けたスクリプトを変数に格納する?
[呼び出し作のスクリプト名] [任意の変数名] = [以前に定義したプロパティ名(オブジェクト)] as [呼び出し作のスクリプト名]
My_Script_WheelMenu_Corde corde_cas = corde as My_Script_WheelMenu_Corde

↑実体化?
エラー"Cannot call X() on a None object, aborting function call"
https://fallout.wiki/wiki/Mod:Creation_Kit/Papyrus...
このエラーは、None のオブジェクト変数に対して非グローバル関数 X が呼び出された場合に表示されます。

スクリプトのReferenceAlias(参照エイリアス?)とCKへの対応

◎スクリプト
ReferenceAlias[] Property Teammates Auto
◎xEdit
・調べたい参照エイリアスをxEditで見つける
・「Propaty」の項目でQuestのIDと名前を調べる
◎CK
・xEditで調べたQuestIDを開く
・該当の「Questウィンドウ→「Scriptタブ」→該当のスクリプト名→該当のプロパティ名→ReferenceAlias

スクリプトのプロパティとCKとの対応

・「Quest」、「Faction」、「Spell」のエイリアス?プロパティ?はCKからそのまま継承?拡張?されている?

◎1.
スクリプト「Quest Property SSLYACRHelperMain Auto」
 ↓
 CKでクエスト「SSLYACRHelperMain」を調べれば出てくる
 →スクリプト「ReferenceAlias Property SSLYACRHelperMainAggr Auto」
   ↓参照エイリアス?
 CKのクエスト「SSLYACRHelperMain」の「Aggr」エイリアス?

◎2.
スクリプト:Faction Property CurrentHireling Auto
CK:派閥「CurrentHireling」


Questエイリアスのメモ

◎Radiant Story
・Radiant Story とは、動的なクエストやその他のストーリー コンテンツを作成するためのシステムを指します。
・その場所、アクター、アイテムは、完全に事前定義されるのではなく、実行時に作成または検索できます。
・システムは「エイリアス」、「シーン」、「ストーリーマネージャー」を含むように拡張されています。

・クエスト(quest )の主な部分は、エイリアス(Aliases)、ステージ(Stages)、目的(Objectives)、対話(Dialogue)『トピック(topics )とシーン(scenes)』です。

Alias(エイリアス)とは?

・エイリアスとは、クエストで使用されるアクター、オブジェクト、および場所に割り当てられた名前またはタグです。
・これにより、さまざまなデータ要素 (スクリプト、パッケージ、ダイアログ) をワールド内の特定のオブジェクトではなくエイリアスにタグ付けできるようになり、クエストでエイリアスを事前定義するのではなく実行時に指定できるようになります。

・エイリアスは、クエストの実行が開始されるまで実際には「入力」されないことに注意してください。
・「クエスト エイリアス」タブで定義されるのは、クエストの開始時にエイリアスがどのように入力されるかです。

・特定のNPCではなくエイリアスに対してダイアログの条件を設定したり、特定のNPCではなくエイリアスにパッケージを与えたりすることができるので、どんなアクターでもクエストでエイリアスの「役になりきる」ことができる。

・エイリアスは事前に定義することができ、多くの場合、事前に定義されています

◎エイリアスの種類
・エイリアスは次の 2 種類があります。
  1. 参照エイリアス (アクターとオブジェクト)
  2. ロケーションエイリアス

クエストデータタブ


◎左上のプルダウンメニュー
ID必須。オブジェクト ウィンドウに表示されるクエスト ID。
クエスト名プレイヤーのクエスト リストに表示されるクエストの名前
「その他」タイプのクエストにはクエスト名が表示されないため、その必要はありません。
目標のないクエストも、どこにもクエスト名が表示されず、クエスト名は必要ありません。
優先度ダイアログは優先度によって割り当てられます。
ダイアログが「スタック」している場合(共有トピックタイプまたはブロック/排他的分岐)、
優先度の高いクエストのダイアログは、優先度の低いクエストのダイアログよりも優先されます。
エイリアスも優先度の影響を受けます。
優先度の低いクエストは、優先度の高い別のクエストのエイリアスに取って代わられます。
イベントイベントを指定するクエストは、ストーリー マネージャーによってのみ開始できます
(「ゲームの開始が有効」はグレー表示されます)。
Event のないクエストは、Start、SetStage、またはSetObjectiveDisplayedを呼び出して「手動」で開始されます。
◎チェックボックス
ゲームの開始を有効にする(Start Game Enabled)このオプションは、トリガーとなるイベントのないクエストでのみ使用できます。
このボックスをチェックすると、ゲームの開始時にクエストの実行が開始されます。
それ以外の場合、 Start、SetStage、またはSetObjectiveDisplayedコマンドが使用されるまで実行は開始されません。
一度実行(Run Once)クエストの開始時にクエストがリセットされないようにします。
「Start Game Enabled」クエストにも「Run Once」フラグが設定されていない場合、そのOnInitイベントは 2 回発生します。
エイリアス埋め込み失敗に関する警告(Warn on alias fill failure)未使用?
繰り返しステージを許可(Allow Repeated Stages)このボックスをチェックすると、特定のステージ番号に対してSetStageが呼び出されるたびにジャーナル エントリが表示されます
(およびクエスト ステージの結果が実行されます) 。
それ以外の場合、SetStage は、実行中のクエストのステージに対して初めて呼び出された後は効果がありません。
タイプこのドロップダウンは、プレイヤーのクエスト リストのクエストの横にどのアイコンが表示されるかを決定します。
また、「その他」タイプにタグ付けされたクエストは「その他」カテゴリに表示されます。
つまり、その目的のみが表示されます (クエスト名や概要テキストは表示されません)。
クエスト条件ここでの条件はすべて、クエスト内のすべての会話に適用されるとみなされます。
最初にクエスト条件がチェックされます。
これらが true の場合にのみ、情報の条件が評価されます。
テキスト表示グローバルこのクエストのテキスト置換に使用するグローバル変数は、このリストに追加する必要があります。

Quest エイリアス タブ

・Quest Alias タブには、このクエストで使用されるエイリアスのリストが含まれています。
・クエストにトリガーイベントがある場合( 「クエストデータ」タブを参照)、タブの上部にリストされます。

・エイリアスのリストは順序付きリストです。クエストが開始されると、エイリアスが順番に入力されます。
・エイリアスが直接的または間接的に (他のエイリアスを参照する条件を通じて) 相互に依存している場合、その順序が重要になることがあります。

ストーリーマネージャー関連

ストーリーマネージャー(Story Manager)とは?

参考:https://www.creationkit.com/index.php?title=Catego...
・ストーリー マネージャーとは、アクターが死亡したとき、プレーヤーが新しい場所に入ったとき、プレーヤーのレベルが上がったときなどのゲーム イベントに基づいてクエストを開始します。
・これらのイベントはゲームによって自動的に生成され、ストーリー マネージャー イベント ノード ([オブジェクトウィンドウ]の [キャラクター] の下にある SM イベント ノード) によって受信され、クエストの開始や他のアクションの実行によって応答できます。
・Story Manager が処理するすべてのイベントには、デシジョン ツリーに編成された一連のデシジョン ノードで構成されるSM イベント ノードがあります。
・ストーリー マネージャーは、開始する単一のクエストを選択するために、ディシジョン ツリーを介して機能します (複数のクエストを開始するために、ディシジョン ツリーをオプションでセットアップできます)。
・ツリー内の各ノードには独自のプロパティとノード条件があり、ストーリー マネージャーにノードを処理する方法と、ツリーのそのパスに沿って続行するかどうかを指示します。ノードには 4 つのタイプがあります。
  1. イベントノード
  2. ブランチノード
  3. クエストノード
  4. クエスト

・Radiant Story システムの中心となるのはStory Managerです。
・これは、すべての Radiant Story Quest を保持するネストされたノード ツリーであり、ゲームから Story Manager イベントを受信した結果としてどのクエストが開始されるかを決定するために使用されます。
・すべての Story Manager イベントには、さまざまなイベント データが付属しています。

・たとえば、「Change Location」イベント データには古い場所と新しい場所が含まれ、「Kill​​ Actor」イベント データには被害者、殺人者、およびその死が殺人犯罪であるかどうかが含まれます。
・このイベント データを使用して、特定の基準を満たすイベントに応答できます。
・これにより、Radiant Story は、プレイヤーのアクションや当面の状況に応じたクエストやシーンを作成したり、プレイヤーをこれまで行ったことのない場所に送ったりするための強力なツールになります。

・イベント データを利用する主な方法は、ストーリー マネージャーのクエストとノードの 条件を使用して、イベント データの詳細を確認することです。

・たとえば、「Run On->Event Data:Victim - GetInFaction MySpecialFaction == 1」という条件を使用して、特定の派閥のメンバーであるアクターの死に応答できます。
・これは、参照として渡されるデータに対して機能します。他のタイプのデータの場合は、特別なGetEventData条件を使用します。

・クエストに添付されたスクリプト上で実行されるPapyrus スクリプト イベントを使用して、クエストを開始する原因となった Story Manager に渡されたデータを調べることもできます。
・たとえば、イベントデータに基づいてクエスト開始時にグローバル変数を設定したい場合です。

ストーリーマネージャーのクエスト

・ストーリー マネージャーからクエストを開始するには、そのクエストが特定のゲーム イベントにタグ付けされている必要があります。
・クエストの [クエスト データ] タブで、クエストにタグ付けするイベントを選択できます。
・クエストにタグが付けられると、そのクエストで使用されるクエスト エイリアスは、イベントが発生した場所やイベントに関与する 1 つ以上のアクターなど、そのイベントのイベント データにアクセスできるようになります。
・最後に、イベントにタグ付けされたクエストは、そのイベントのSM イベント ノードに追加する必要があり、ストーリー マネージャーを通じてのみ開始できます。

ストーリーマネージャーの仕組み

イベントのトリガー
・イベントは、そのタイプに応じて常に同じ方法でトリガーされます。
・たとえば、アクターが死亡すると Kill Actor イベントが常に発生し、プレイヤーがアイテムを作成すると Craft Items イベントが常にトリガーされます。
・トリガーされたイベントは、すべてのイベント データをストーリー マネージャーに渡します。
・このデータは主に、ストーリー マネージャーが開始するクエストのクエスト エイリアスを埋めるため、およびストーリー マネージャー自体が特定の条件に基づいてのみクエストを開始するように条件付けするために使用されます。
クエストの開始

複数のクエストを開始する

SMイベントノード(ストーリーマネージャー用のイベント?)

参考:https://www.creationkit.com/index.php?title=SM_Eve...
・SMイベント ノードを使用すると、ストーリー マネージャーを使用して、ゲーム イベントに基づいてクエストを開始できます
 (たとえば、アクターの殺害イベントを使用してアクターが殺害されるたびにクエストを開始できます)。
・イベント ノードのリストがオブジェクト ウィンドウの Character の下に表示されます。

■イベントのリスト(一部)
アクター対話イベントhttps://www.creationkit.com/index.php?title=Actor_...
アクターハローイベントhttps://www.creationkit.com/index.php?title=Actor_...
逮捕イベントArrest Event衛兵が別の俳優を逮捕するたびにイベントがトリガーされます。https://www.creationkit.com/index.php?title=Arrest...
アクター攻撃イベントAssault Actor Eventアクター (通常はプレイヤー) が別のアクターに対してアサルトをコミットするたびにトリガーされるイベント。https://www.creationkit.com/index.php?title=Assaul...
プレーヤーがアクターをアクティブにするPlayer Activate Actorプレイヤーが別のアクタに近づき、Hello リアクションをトリガーするたびにイベントがトリガーされます。https://www.creationkit.com/index.php?title=Player...
場所変更イベントChange Location Eventプレーヤーが新しいLocationに入るたびにトリガーされるイベント。https://www.creationkit.com/index.php?title=Change...
スクリプトイベントScript Eventスクリプト コマンドSendStoryEventによって作成されたイベント。https://www.creationkit.com/index.php?title=Script...

SMイベントノードウィンドウ


シーン(scenes)とは?

参考:https://www.creationkit.com/index.php?title=Catego...
・シーンは、会話における複数の NPC の調整や、さまざまな「カット シーン」を処理します。
・シーンにはダイアログ(dialogue)、タイマー(timers)、パッケージ(packages)が含まれます。
・シーンはランダムな 2 人の NPC 間の単純な会話から、クエストのための精巧なセットピースまで多岐にわたります。

・シーンに含めるエイリアスを選択し、さまざまなフェーズにわたる各エイリアスのパッケージ アクションとダイアログ アクションを定義します。
・フェーズ、パッケージ アクション スタック、ダイアログ アクション スタックはすべて条件を持つことができるため、さまざまなシーンにバリエーションやコントロールを追加できます。

◎シーンのフェーズ
・シーンには、フェーズの連続リストが含まれます。各フェーズはシーンの個別のチャンクです。
・フェーズ 1 が完了すると、シーンはフェーズ 2 に進みます。
・シーンの最後のフェーズが完了すると、シーンは終了します。

◎シーンのアクション
・各フェーズには、シーンに割り当てられた各アクターの一連のアクションが含まれています。
・同じフェーズで発生するアクションは同時です。つまり、各アクターがシーンのこの部分で行っていることです。
・アクションには次の 3 種類があります。
  • 対話(dialogue)
  • パッケージ(packages)
  • タイマー(timers)

シーンの仕組み

・シーン流れ「シーンの開始」→「フェーズの開始」→「フェーズの完了」→「シーンの終了」
シーンの開始
◎シーンの開始方法
  • 「クエスト開始時に開始(Begin on quest start)」のフラグが付いたシーンは、クエストの開始時に自動的に開始されます。
  • スクリプト コマンド「Start _-_Scene」 がシーン上で呼び出される
・シーンが開始されると、シーン上の「開始」フラグメントが実行され、フェーズ 1 の開始条件をチェックしてシーンが開始されます。
フェーズの開始
・シーンは、そのフェーズの開始条件をチェックすることによって、現在のフェーズを開始するかどうかを確認します。
・それらが真の場合、フェーズが開始されます。
・開始条件が false の場合、フェーズはスキップされます
  (このフェーズの開始スクリプト フラグメントも完了スクリプト フラグメントも実行されません)。
・フェーズが開始すると、開始スクリプト フラグメントが実行され、このフェーズで開始されるアクションが適切なアクターに割り当てられます。
フェーズの完了
・シーンは、フェーズが終了するまでこのフェーズに残ります。
◎フェーズが終了する条件
  • そのフェーズで終了するすべてのアクションが完了している
  • そのフェーズの「終了条件」が true

◎アクションの完了する条件
  • パッケージのアクションは、パッケージが「完了」状態に達すると完了します。
 「完了」状態のないパッケージを含むアクションは決して完了できません。
 この種のアクションを含むフェーズを終了するには、完了条件を使用する必要があります。
  • 対話アクションは、俳優がセリフを話し終わると完了します。
  • タイマー アクションは、タイマーが期限切れになると完了します。
・死亡したアクターまたは無効化されたアクターに対するアクションは、すぐに完了したとみなされることに注意してください
 (死んだ/障害のある俳優は話したり、パッケージを実行したりしません。)
・フェーズが終了すると、シーンが次のフェーズに進む前に、フェーズの完了スクリプト フラグメントが実行されます。
 その後、シーンは次のフェーズの開始条件をチェックするなどして続行されます。
シーンの終了
◎シーンの終了方法
  • シーンの最終フェーズが終了する場合
  • シーン内のアクターの 1 人が、シーンを終了するようにマークされているステートに到達した場合
  • シーンに「中断可能」のフラグが立てられ、このシーンの 1 人以上のアクターを必要とする別のシーンが開始さた場合
  • プレイヤー キャラクターが、シーンが再生されている外部から内部に、またはその逆に遷移した場合
  • シーンの探索が停止された場合
  • スクリプトで「Stop」が呼びかけられた場合
・シーンがどのように終了しても、シーンの「終了」スクリプト フラグメントが呼び出されます。
繰り返しのシーン
・シーンで「Repeat while true」フラグがチェックされている場合、シーンの終了時に「Repeat」条件がチェックされます。
・true の場合、シーンが再開されます。
・シーンの Begin スクリプト フラグメントと End スクリプト フラグメントはそれぞれ 1 回だけ実行されることに注意してください。
・Begin はシーンが最初に開始するときに実行され、End はシーンが実際に終了するときに実行されます。
・シーンがループするたびに実行されるわけではありません。

会話のシーン関連

ランダムな会話(Random Conversations)
・アクターが互いに会話を開始しようとするとゲームは
 「Actor Hello Event」と「Actor Dialogue Event」
 の2 種類のイベントを送信します。

・ストーリー マネージャーの適切なノードに配置されたクエストは、これらのイベントに応答するために使用されます。
 (これは、Fallout と Oblivion で使用されていた会話システムを置き換えます。)

・このプロセスを合理化する方法として、
 シーンに「クエスト開始時に開始(Begin on quest start)」(クエストの開始時にシーンが自動的に開始される)、 
 および「シーン終了時にクエストを終了(End quest on scene end)」(シーンの終了時にクエストを停止する)の
 マークを付けることができます。
アクターハローイベント(Actor Hello Event)
参考:https://www.creationkit.com/index.php?title=Actor_...
・NPC がすれ違いながら別の NPC と ランダム会話を開始しようとするたびにトリガーされるイベント。
・このイベントは、動いているアクター (「ランダム会話」フラグで許可されている場合) が動いていないアクターの近くを通過したときに送信されます。

・イベントが送信されると、AI コードはアクターの動作を変更したり制御したりすることはありません
 (アクター ダイアログ イベントとは異なります )
・AI の動作はすべて、トリガーされたシーン内のパッケージ アクションによって処理される必要があります。

◎開始側アクターは次のことを行う必要があります。
  1. 動いてください(Be moving)
  2. シーンにいない(Not be in a scene)
  3. 新しいヘッドトラックターゲットを見つけました(Have picked up a new headtrack target)

◎有効なターゲット アクター:
  1. プレイヤーではありません
  2. シーンにない

◎イベントデータ
  • アクター 1: 会話を開始したアクター。
  • アクター 2: 開始されるアクター。
  • 場所: 会話が行われる場所。
アクター対話イベント(Actor Dialogue Event)
参考:https://www.creationkit.com/index.php?title=Actor_...
・NPC が別の NPC とランダム会話を開始するたびにトリガーされるイベント。
・このイベントは、アクターが (パッケージの「ランダム会話」フラグで許可されている場合) 有効な会話ターゲットを見つけたときに送信されます。

・イベントがシーンをトリガーすると、AI コードは両方のアクターを「中断動作(interrupt behavior)」で制御します。
・イベントを開始したアクターは、会話のターゲット アクターに向かって歩きます。
・ターゲット アクターは移動を停止しますが、アイドル マーカーまたは家具を使用し続けます。
・トリガーされたシーンは、開始アクターがfAIMinGreetingDistance (150 単位)に達するまで、「フェーズ 0」(フェーズ 1 の前) で一時停止されます。

◎イベントデータ
アクター 1: 会話を開始したアクター。
アクター 2: 開始されるアクター。
場所: 会話が行われる場所。
ランダムな会話を制御する
ランダムな NPC の会話は、次のゲーム設定によって制御されます。
ゲーム設定値(Value)説明
fAISocialRadiusToTriggerConversation2000この半径の外側にあるアクターは、相互に会話を開始しようとしません (外部)
AISocialRadiusToTriggerConversationInterior1000この半径の外側にあるアクターは、互いに会話を開始しようとしません (内部)
fAISocialchanceForConversation25攻撃者がランダムな会話を開始することを選択する確率のパーセント
fAISocialchanceForConversationInterior25アクターがランダムな会話を開始することを選択する確率 (内部)
fAItalktosameNPCTimer120同じ俳優と再び会話できるようになるまでの時間 (秒)
fAISocialTimerForConversationsMin30このアクターが次回ランダムな会話を開始しようとするときのタイマーの最小値
fAISocialTimerForConversationsMax60このアクターが次回ランダムな会話を開始しようとするときのタイマーの最大値
iAISocialDistanceToTriggerEvent120ランダムな会話を開始するときに、俳優がどの程度親密になりたいか
fAISocialTimerToWaitForEvent0.5アクターダイアログイベントを起動した後、シーンマネージャーがランダムな会話シーンを返すまでアクターが待つ時間

■使い方:
・このNPC がすでにシーン内にいる場合や、プレイヤーがすでに重要な会話に参加している場合、またはグローバル「複雑なシーン(complex scene)」フラグが設定されている場合にはイベントを送信しません。
・NPC のパッケージには、「ランダム会話(Random Conversations.)」を許可するフラグが設定されている必要があります。
・NPC は「ソーシャル半径(social radius)」内で有効なターゲットを探します。
  ・デフォルトの「ソーシャル半径」は、外部では fAISocialRadiusToTriggerConversation、内部では fAISocialRadiusToTriggerConversationInterior です。
  ・NPC がサンドボックス パッケージ内にある場合、「ソーシャル半径」は NPC のサンドボックス半径に置き換えられます。
・有効なターゲットがある場合は、「ソーシャル チャンス」を獲得します (fAISocialchanceForConversation/fAISocialchanceForConversationInterior)
・ロールが成功すると、NPC はターゲット NPC に歩み寄ります。
 (iAISocialDistanceToTriggerEvent) 距離内にある場合は、Actor Dialogue イベントを送信し、(fAISocialTimerToWaitForEvent) 秒間待機して、シーンが開始されたかどうかを確認します。
・シーンが終了したら、(fAISocialTimerForConversationsMin と fAISocialTimerForConversationsMax) の間でタイマーをロールします。
・タイマーが切れたら、プロセスを最初からやり直します。

◎有効な会話ターゲット:
・アクターは「Random Conversations」パッケージ フラグをチェックする必要があります。
・fAItalktosameNPCTimer 秒以内に同じアクターと会話できません。
・アクターは割り込み動作を行ってはなりません。

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu

【メニュー編集】

スカイリム関連

スカイリム関連


Menu

【メニュー編集】

スクリプト関連

フリーエリア

管理人/副管理人のみ編集できます