exmlファイルの編集方法 - Kizari/Flagrum GitHub Wiki
Click here for the English version of this guide.
このガイドでは、奇妙な表現があることをお許しください。
私は日本語を話すことができないので、翻訳機を使って書いています。
- 必要条件
- はじめに
- 編集用exmlファイルの取得
- exmlファイルの構造
- ノード間の接続
- コンテナ・オブジェクト
- 既存の動作を削除する
- 既存の行動を変える
- 新しいビヘイビアを追加する
-
編集したファイルをゲームに戻す
以下の項目が必要です。
- Final Fantasy XV Windows Edition
- Flagrum
- テキストエディタ(XMLの構文が扱えるものが望ましい)。
exml ファイルは、Unreal Engine の「ブループリント」に似ています。これは、ゲームに実行させる一連のアクションを作成するために、互いに接続されたノードのグループです。
この画像は、exmlファイルを視覚的に表現したものです。写真のツールは現在使用できません。
exml ファイルは、データ表現の一般的な標準である XML と呼ばれるテキストベースのフォーマットで格納されています。 XMLについてもっと学ぶことで、exmlがどのように動作するかの理解を深めることができます。しかし、このガイドが重要な概念のほとんどをカバーしているので、これは必須ではありません。
下の表は、exmlの異なるファイル拡張子の意味を説明しています。
ファイル拡張子 | 氏名(ふりがな | 用途 |
---|---|---|
ebex | Ebony Entity XML | XMB2に変換される前のXMLファイルです。 |
exml | Ebony XML | XMB2に変換された後のXMLファイルです。これを編集できるようにXMLに変換するためにFlagrumが使用されます。 |
xmb | XML Binary | これは、ゲームで使用されるXMLのバイナリ形式です。FF15の古いデモでのみ使用されています。 |
xmb2 | XML Binary Version 2 | これは、XMLのバイナリ形式のバージョン2です。XMB2は、FF15のリリース版で使用されています。 |
prefab | Prefabricated | これもexmlファイルの一種で、環境用にグループ化するために使われる。事実上 ebex と同じである。 |
Flagrumの「Asset Explorer」は、exmlファイルを取得するのに最適なツールです。これらのファイルはXMB2形式ですが、ファイルを左クリックするとFlagrumが自動的にXMLに変換して読み込んでくれます。 ファイルを編集するには、右クリックして「Export as XML」を選択し、ファイルをディスクに保存する必要があります。保存されたファイルは、お好みのXMLエディターで開いて変更することができます。
警告: Flagrumの中の単語を検索するために「Ctrl + F」を使用しないでください。
現在画面に表示されているテキストのみを検索します。
テキストを検索する必要がある場合は、まずファイルをXMLとしてエクスポートしてください。
すべてのexmlファイルは <package>
要素を含んでおり、これはファイルの内容を格納する単なるコンテナである。これを編集する必要は決してありません。
<package>
要素のすぐ内側に <objects>
要素があります。 この要素は、複数の <object>
要素がその中にあることを単に示しています。
<package name="Name_of_Package">
<objects>
...
</objects>
</package>
<object>
要素は exml ファイルで最も重要な部分である。<object>
はノードでもコンテナでもよい。
<object objectIndex="75" ownerPath="nodes_" checked="True" type="SQEX.Ebony.Framework.Sequence.Variable.SequenceConstInt" path="entities_.Ctrl.nodes_.[0].nodes_.[38].nodes_.[3]" name="[3]" ownerIndex="71" owner="entities_.Ctrl.nodes_.[0].nodes_.[38]">
<out_>
<connections_>
<reference objectIndex="72" reference="True" relativePath="refInPorts_.Mode" object="entities_.Ctrl.nodes_.[0].nodes_.[38].nodes_.[0]" />
</connections_>
</out_>
<value_ type="int">2</value_>
</object>
上の例はノードだが、コンテナでも <object>
の構造は同じである。下の表は、<object>
の各属性がどのような働きをするかを説明したものです。
アトリビュート | 用途 |
---|---|
objectIndex | この番号で <object> を識別する。同じ「objectIndex」を持つ <object> は1つのexmlファイル内に1つしかない。 |
ownerPath | このオブジェクトが含まれるコンテナへのパスである。 |
checked | これは、オブジェクトがアクティブかどうかを判断するものである。 |
type | これが最も重要な属性です。「type」は <object> の振る舞いを決定します。 |
path | これは <object> 自体へのパスである。 |
name | これは <object> の名前であり、同じコンテナ内の他の <object> と同じであってはならない。 |
ownerIndex | この <object> が含まれるコンテナ <object> の 「objectIndex」である。 |
owner | この <object> が含まれるコンテナ <object> の「path」を指定する。 |
これらの属性は、独自のノードを追加する際に正しい値を設定する必要があるため、各属性の役割を覚えておくことが重要です。
ノードは互いに接続され、全体的なイベントのシーケンスを作成します。
接続には2種類あります。
- トリガー接続は、どの順番でノードを実行するかをゲームに指示します。
-
変数接続は、あるノードから別のノードに値を渡します。
トリガー接続は黄色で表示されています。可変の接続は赤で表示されます。
通常、ノードは同じコンテナ内でなければ正常に接続できない。
以下の例では、わかりやすくするために、一部のデータを省略しています。
<object objectIndex="2" ownerIndex="1">
<out_>
<connections_>
<reference objectIndex="3" reference="True" relativePath="_in" object="entities_.nodes_.[6]" />
</connections_>
</out_>
</object>
上記の例を 「object 2」として参照する。
<object objectIndex="3" ownerIndex="1">
<in_>
<connections_>
<reference objectIndex="2" reference="True" relativePath="_out" object="entities_.nodes_.[5]" />
</connections_>
</in_>
</object>
上記の例を 「object 3」として参照する。
「object 2」は <out_>
という要素を持っています。これは、含まれる <connections_>
要素の存在により、コネクタと推論することができます。 <out_>
は出力接続であることを意味する。
同様に、「object 3」にもコネクタがあります。しかし、こちらは <in_>
コネクタであり、入力接続であることを意味します。
両ノードは同じ「ownerIndex」を持つので、同じコンテナ内に含まれています。したがって、これらは正常に接続することができます。
ノードが完全に接続されるには、両端が接続されている必要があります。
コネクションは、<connections>
要素内に他のノードへの参照を追加することで作成される。
<reference>
要素はこれらの参照を定義し、次のような構造になっています。
アトリビュート | 用途 |
---|---|
objectIndex | このノードが接続されるノードの 「objectIndex」 である。 |
reference | これにより、リファレンスであることが確認されました。これは常に 「True」である。 |
relativePath | 参照されるノードからコネクタまでのパスです。 |
object | これが接続されるノードの「path」である。 |
上の表を使うと、「object 2」が実行し終わったら、出力コネクタを介して「object 3」に接続し、次にそれを実行することがわかります。
上記の例をビジュアルに表現したものです。
exmlでは、コンテナは他の <object>
を保持することができる <object>
である。
コンテナ内にグループ化されたいくつかのノードを視覚的に表現したものです。
ゲームの挙動は、ほとんど「シーケンス」で制御されています。 コンテナの例として、すべてのシーケンスには、イベントのシーケンスの一部であるすべてのノードを含むシーケンスコンテナ(「SequenceContainer」)があります。
<object objectIndex="1" ownerPath="entities_" checked="True" type="SQEX.Ebony.Framework.Sequence.SequenceContainer" path="entities_.Layout" name="Layout" ownerIndex="0" owner="">
<updateAtPause_ type="bool">False</updateAtPause_>
<nodes_>
<reference objectIndex="2" reference="True" object="entities_.Layout.nodes_.[70]" />
<reference objectIndex="3" reference="True" object="entities_.Layout.nodes_.[71]" />
<reference objectIndex="4" reference="True" object="entities_.Layout.nodes_.[72]" />
<reference objectIndex="5" reference="True" object="entities_.Layout.nodes_.[73]" />
<reference objectIndex="6" reference="True" object="entities_.Layout.nodes_.[74]" />
<reference objectIndex="7" reference="True" object="entities_.Layout.nodes_.[75]" />
<reference objectIndex="8" reference="True" object="entities_.Layout.nodes_.[76]" />
<reference objectIndex="9" reference="True" object="entities_.Layout.nodes_.[82]" />
<reference objectIndex="10" reference="True" object="entities_.Layout.nodes_.[83]" />
<reference objectIndex="11" reference="True" object="entities_.Layout.nodes_.[84]" />
<reference objectIndex="12" reference="True" object="entities_.Layout.nodes_.[77]" />
<reference objectIndex="13" reference="True" object="entities_.Layout.nodes_.[81]" />
<reference objectIndex="14" reference="True" object="entities_.Layout.nodes_.[80]" />
<reference objectIndex="15" reference="True" object="entities_.Layout.nodes_.[79]" />
<reference objectIndex="16" reference="True" object="entities_.Layout.nodes_.[78]" />
</nodes_>
<lastCenterX_ type="float">457.4387</lastCenterX_>
<lastCenterY_ type="float">52.94099</lastCenterY_>
<bIsPrefabTopSequence_ type="bool">True</bIsPrefabTopSequence_>
</object>
<nodes_>
要素の存在が、この <object>
がコンテナであることを決定している。
<nodes_>
要素内の参照は、コンテナ内にどのノードが存在するかを決定する。これらの参照の構造は、「ノード間の接続」のセクションの参照と同じである。
コンテナによっては、<nodes_>
要素の代わりに <entities_>
要素を持つことがあります。これらは同じように動作する。
この例では、ガーディナ渡船場からフォトコンテストのポップアップを削除することで、その概念を示します。
下のファイルが修正されるものです。
data://level/world/area_leide/map_galdin/location/map_le_gq_a_location.ebex
まず、ポップアップのトリガーとなる振る舞いの場所を特定する必要があります。
このファイルの先頭付近に、次のような行があります。
<reference objectIndex="22" reference="True" object="entities_.trigger_photo_contest" />
「trigger_photo_contest」は「トリガーフォトコンテスト」と訳されますが、これは何を判断材料にするかということです。この参照は objectIndex="22"
を指しているので、<object objectIndex="22"
を検索して対応する <object>
を見つけることができる。
<object objectIndex="22" ownerPath="entities_" checked="True" type="Black.Entity.EntityGroup" path="entities_.trigger_photo_contest" name="trigger_photo_contest" ownerIndex="0" owner="">
<entities_>
<reference objectIndex="23" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest" />
<reference objectIndex="38" reference="True" object="entities_.trigger_photo_contest.entities_.triggerentity01" />
<reference objectIndex="39" reference="True" object="entities_.trigger_photo_contest.entities_.gal_restaurant_int_photocontest1" />
<reference objectIndex="40" reference="True" object="entities_.trigger_photo_contest.entities_.trigger_in_out_diner" />
<reference objectIndex="41" reference="True" object="entities_.trigger_photo_contest.entities_.trigger_in_out_diner01" />
<reference objectIndex="42" reference="True" object="entities_.trigger_photo_contest.entities_.gal_restaurant_int_photocontest_bu" />
<reference objectIndex="43" reference="True" object="entities_.trigger_photo_contest.entities_.gal_restaurant_int_photocontest_bd" />
<reference objectIndex="44" reference="True" object="entities_.trigger_photo_contest.entities_.gal_restaurant_int_photocontest_fu" />
<reference objectIndex="45" reference="True" object="entities_.trigger_photo_contest.entities_.gal_restaurant_int_photocontest_fd" />
</entities_>
<hasTransform_ type="bool">False</hasTransform_>
<position_ type="float4">0,0,0,0</position_>
<rotation_ type="float4">0,0,0,0</rotation_>
<scaling_ type="float">1</scaling_>
<canManipulate_ type="bool">True</canManipulate_>
</object>
<entities_>
要素の存在は、これが別のコンテナであることを示す。したがって、この振る舞いを担うノードを見つけるために、さらに深く掘り下げる必要があります。
「info_photo_contest」は「フォトコンテスト情報」と訳され、次に見るべき場所であることが推測されます。ここでも、「objectIndex」を使って次の <object>
を特定する。
<object objectIndex="23" ownerPath="entities_" checked="True" type="SQEX.Ebony.Framework.Sequence.SequenceContainer" path="entities_.trigger_photo_contest.entities_.info_photo_contest" name="info_photo_contest" ownerIndex="22" owner="entities_.trigger_photo_contest">
<nodes_>
<reference objectIndex="24" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[1]" />
<reference objectIndex="25" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[8]" />
<reference objectIndex="26" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[12]" />
<reference objectIndex="27" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[15]" />
<reference objectIndex="28" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[17]" />
<reference objectIndex="29" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[18]" />
<reference objectIndex="30" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[19]" />
<reference objectIndex="31" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[20]" />
<reference objectIndex="32" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[21]" />
<reference objectIndex="33" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[22]" />
<reference objectIndex="34" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[23]" />
<reference objectIndex="35" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[0]" />
<reference objectIndex="36" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[24]" />
<reference objectIndex="37" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[25]" />
</nodes_>
<lastCenterX_ type="float">482.203</lastCenterX_>
<lastCenterY_ type="float">96.28064</lastCenterY_>
<bIsPrefabTopSequence_ type="bool">True</bIsPrefabTopSequence_>
</object>
もう一つの容器。今回は、次にどこを見るべきかという情報がないため、それぞれの <object>
を調べて手がかりを探すことになる。
<object objectIndex="25" ownerPath="nodes_" checked="True" type="Black.Sequence.Action.Menu.SequenceActionTutorialInfoWindow" path="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[8]" name="[8]" ownerIndex="23" owner="entities_.trigger_photo_contest.entities_.info_photo_contest">
<Isolated_ type="bool">False</Isolated_>
<in_>
<connections_>
<reference objectIndex="29" reference="True" relativePath="out_" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[18]" />
</connections_>
</in_>
<dispTime_ type="float">0</dispTime_>
<dispFixTime_ type="float">0.5</dispFixTime_>
<flagSkipPermit_ type="bool">False</flagSkipPermit_>
<flagPause_ type="bool">True</flagPause_>
<messageSpecificationType_ value="0" type="enum">SPECIFICATION_FIXID</messageSpecificationType_>
<dialogFixId_ type="Fixid" fixid="184667666">level_nox00_march18_ui_contest_message010_010</dialogFixId_>
</object>
2ノード後に、この1ノードにたどり着きます。先に述べたように、「type」は各ノードの振る舞いを決定する。 「TutorialInfoWindow」は「チュートリアル情報ウィンドウ」と訳され、情報ポップアップと推察される。
望ましくない振る舞いをするノードが特定されたので、そのノードへの参照も含めて削除しなければならない。
ノードの正しい削除
まず、 <object
と </object>
の間をすべて削除してください。これで、ノードそのものが削除されます。
<reference objectIndex="25"
を検索して、このノードへのすべての参照を見つける。
最初のリファレンスは、先にシーケンスコンテナで見つかったものです。このリファレンスは削除する必要があります。
変更前
<object objectIndex="23" ownerPath="entities_" checked="True" type="SQEX.Ebony.Framework.Sequence.SequenceContainer" path="entities_.trigger_photo_contest.entities_.info_photo_contest" name="info_photo_contest" ownerIndex="22" owner="entities_.trigger_photo_contest">
<nodes_>
<reference objectIndex="24" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[1]" />
<reference objectIndex="25" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[8]" />
<reference objectIndex="26" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[12]" />
<reference objectIndex="27" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[15]" />
<reference objectIndex="28" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[17]" />
<reference objectIndex="29" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[18]" />
<reference objectIndex="30" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[19]" />
<reference objectIndex="31" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[20]" />
<reference objectIndex="32" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[21]" />
<reference objectIndex="33" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[22]" />
<reference objectIndex="34" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[23]" />
<reference objectIndex="35" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[0]" />
<reference objectIndex="36" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[24]" />
<reference objectIndex="37" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[25]" />
</nodes_>
<lastCenterX_ type="float">482.203</lastCenterX_>
<lastCenterY_ type="float">96.28064</lastCenterY_>
<bIsPrefabTopSequence_ type="bool">True</bIsPrefabTopSequence_>
</object>
変更後
<object objectIndex="23" ownerPath="entities_" checked="True" type="SQEX.Ebony.Framework.Sequence.SequenceContainer" path="entities_.trigger_photo_contest.entities_.info_photo_contest" name="info_photo_contest" ownerIndex="22" owner="entities_.trigger_photo_contest">
<nodes_>
<reference objectIndex="24" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[1]" />
<reference objectIndex="26" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[12]" />
<reference objectIndex="27" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[15]" />
<reference objectIndex="28" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[17]" />
<reference objectIndex="29" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[18]" />
<reference objectIndex="30" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[19]" />
<reference objectIndex="31" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[20]" />
<reference objectIndex="32" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[21]" />
<reference objectIndex="33" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[22]" />
<reference objectIndex="34" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[23]" />
<reference objectIndex="35" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[0]" />
<reference objectIndex="36" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[24]" />
<reference objectIndex="37" reference="True" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[25]" />
</nodes_>
<lastCenterX_ type="float">482.203</lastCenterX_>
<lastCenterY_ type="float">96.28064</lastCenterY_>
<bIsPrefabTopSequence_ type="bool">True</bIsPrefabTopSequence_>
</object>
2つ目のリファレンスは、「object 29」への接続です。これは <out_>
コネクタへの唯一の接続であるため、コネクタ全体を削除しても安全です。もし <out_>
内に他の参照があった場合は、上記のシーケンスコンテナと同じ方法で 「object 25」 への参照のみを削除します。
変更前
<object objectIndex="29" ownerPath="nodes_" checked="True" type="Black.Sequence.Control.GameFlag.SequenceActionControlSetGameFlagFixId" path="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[18]" name="[18]" ownerIndex="23" owner="entities_.trigger_photo_contest.entities_.info_photo_contest">
<in_>
<connections_>
<reference objectIndex="28" reference="True" relativePath="false_" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[17]" />
</connections_>
</in_>
<out_>
<connections_>
<reference objectIndex="25" reference="True" relativePath="in_" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[8]" />
</connections_>
</out_>
<label_ type="Fixid" fixid="17122781">HU_TOWN_HH_PHOTO_CONTEST_ONE_FIRST</label_>
<valuePin_>
<isBrowsable_ type="bool">False</isBrowsable_>
</valuePin_>
<labelPin_>
<isBrowsable_ type="bool">False</isBrowsable_>
</labelPin_>
<value_ type="int">1</value_>
<isFixid_ type="bool">False</isFixid_>
</object>
変更後
<object objectIndex="29" ownerPath="nodes_" checked="True" type="Black.Sequence.Control.GameFlag.SequenceActionControlSetGameFlagFixId" path="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[18]" name="[18]" ownerIndex="23" owner="entities_.trigger_photo_contest.entities_.info_photo_contest">
<in_>
<connections_>
<reference objectIndex="28" reference="True" relativePath="false_" object="entities_.trigger_photo_contest.entities_.info_photo_contest.nodes_.[17]" />
</connections_>
</in_>
<label_ type="Fixid" fixid="17122781">HU_TOWN_HH_PHOTO_CONTEST_ONE_FIRST</label_>
<valuePin_>
<isBrowsable_ type="bool">False</isBrowsable_>
</valuePin_>
<labelPin_>
<isBrowsable_ type="bool">False</isBrowsable_>
</labelPin_>
<value_ type="int">1</value_>
<isFixid_ type="bool">False</isFixid_>
</object>
これで完了です。ガーディナ渡船場入力時にポップアップが表示されないようになります。
もし、あなたが自分の例で作業をしていて、削除するノードが <out_>
コネクタを持っている場合、削除されたノードの <out_>
コネクタ内のすべての参照は、もはや機能しないことに留意してください。もしこれが望ましい結果でないなら、これらの参照はシーケンス内の前のノードに移動させる必要があります。
ノードの種類は無数にあり、テストされているものも非常に少ないので、現在このプロセスを詳細に説明することはできません。
一般的なアイデアは、ノード内部の値(参照以外)を変更し、ゲームに観測可能な効果をもたらすことです。
このコンセプトを実証するために、以下のMODでは、チョコボのレンタル上限を7日から30日に増やします。
このMODの作り方を発見してくれたRinualさんに感謝します。
この例では、次のファイルを使用します。
data://menu/chocobo_menu/script/menuswfentry_chocoborental.ebex
まず、変えたい行動を見つけることです。
チョコボレンタルが最大7日間限定であることはすでに分かっているので、値7で検索してみましょう。しかし、このファイルでは7という数字が167カ所も出てくるので、絞り込み検索が必要です。
ノードで使用される値は常に要素内に含まれるため、代わりに「>7<」を探すことで検索を絞り込むことができます。今回は、結果は1つだけです。
<object objectIndex="34" ownerPath="nodes_" checked="True" type="SQEX.Ebony.Framework.Sequence.Variable.SequenceConstInt" path="entities_.Ctrl.nodes_.[0].nodes_.[62]" name="[62]" ownerIndex="4" owner="entities_.Ctrl.nodes_.[0]">
<out_>
<connections_>
<reference objectIndex="16" reference="True" relativePath="refInPorts_.refIn2" object="entities_.Ctrl.nodes_.[0].nodes_.[55]" />
</connections_>
</out_>
<value_ type="int">7</value_>
</object>
これは非常にシンプルなMODです。7を30に変えるだけでMODは完成します。
<object objectIndex="34" ownerPath="nodes_" checked="True" type="SQEX.Ebony.Framework.Sequence.Variable.SequenceConstInt" path="entities_.Ctrl.nodes_.[0].nodes_.[62]" name="[62]" ownerIndex="4" owner="entities_.Ctrl.nodes_.[0]">
<out_>
<connections_>
<reference objectIndex="16" reference="True" relativePath="refInPorts_.refIn2" object="entities_.Ctrl.nodes_.[0].nodes_.[55]" />
</connections_>
</out_>
<value_ type="int">30</value_>
</object>
この例のMODでは、カメラの開閉によって、ゲーム内のどこでも「覚醒ノクト」を有効にすることができます。
このMODでは、以下のexmlファイルが必要です。
フォトメニュー
data://menu/photo_mode/script/menuswfentry_photomode.ebex
リヴァイアサン戦
data://quest/ravettrice/scenario_ch03/qt_ch03_0020/qt_ch03_0020_reviathan_last_battle.ebex
まず、「覚醒ノクト」を起動させるノードを探します。
ノクトのステータスを 「STATUS_KNIGHTS_OF_EOS」にすることで、このモードを有効にできることが判明しました。
リヴァイアサン戦のexmlファイルから「STATUS_KNIGHTS_OF_EOS」を検索してください。結果は2つありますが、どちらか一方でも構いません。
<object objectIndex="20" ownerPath="nodes_" checked="True" type="Black.Sequence.Actor.SequenceActionActorSetStatusInt" path="entities_.qt_ch03_0020_reviathan_last_battle.nodes_.[85].nodes_.[1]" name="[1]" ownerIndex="19" owner="entities_.qt_ch03_0020_reviathan_last_battle.nodes_.[85]">
<Isolated_ type="bool">False</Isolated_>
<in_>
<connections_>
<reference objectIndex="28" reference="True" relativePath="out_" object="entities_.qt_ch03_0020_reviathan_last_battle.nodes_.[85].nodes_.[23]" />
</connections_>
</in_>
<out_>
<connections_>
<reference objectIndex="24" reference="True" relativePath="in_" object="entities_.qt_ch03_0020_reviathan_last_battle.nodes_.[85].nodes_.[7]" />
</connections_>
</out_>
<inValue_>
<connections_>
<reference objectIndex="22" reference="True" relativePath="actor_" object="entities_.qt_ch03_0020_reviathan_last_battle.nodes_.[85].nodes_.[3]" />
</connections_>
</inValue_>
<int_>
<connections_>
<reference objectIndex="21" reference="True" relativePath="get_" object="entities_.qt_ch03_0020_reviathan_last_battle.nodes_.[85].nodes_.[2]" />
</connections_>
</int_>
<target_ value="0" type="enum">TARGET_OWN</target_>
<kind_ value="789" type="enum">STATUS_KNIGHTS_OF_EOS</kind_>
<value_ type="int">0</value_>
</object>
このノードが何をするのか理解しましょう。
- タイプを観察する。「ActorSetStatusInt」は、指定されたアクターのステータスを指定された値に設定することを意味します。
-
<in_>
要素で示されるように、ノードに入るトリガー接続が1つあります。 -
<out_>
要素で示されるように、ノードから外に出るトリガ接続が1つあります。 -
<inValue_>
で示されるように、他のノードから入ってくる変数接続が1つあります。 -
<int_>
で示されるように、このノードから出る変数接続は1つです。 -
<target_>
はステータスを適用する対象である。 -
<kind_>
はターゲットに適用されるステータスです。 -
<value_>
は適用するステータスの値である。この場合、0はステータスを無効にすることを意味し、1はステータスを有効にすることを意味する。
この例では、ステータスをオンにした後の動作は必要ないため、<out_>
コネクタは必要ありません。これは削除することができます。
<inValue_>
は <value_>
要素に設定された値を上書きする。単純に <value_>
要素に欲しい値を設定する方が簡単でしょうから、<inValue_>
は削除してもよいでしょう。
このノードの値を他のノードに渡す必要はないので、<int_>
コネクタも削除することができます。
次に、<target_>
をノクトに設定する必要があります。リヴァイアサン戦exmlファイルで 「TARGET_PLAYER_NOCTIS」 を検索すると、次のような行が見つかります。
<target_ value="10" type="enum">TARGET_PLAYER_NOCTIS</target_>
「覚醒ノクト」ノードの<target_>行をこの行に置き換えて修正することができます。
最後に、<value_>要素の値を1にして、ステータスの適用が必要であることを示す。
更新されたノードは、ここまででこのように表示されるはずです。
<object objectIndex="20" ownerPath="nodes_" checked="True" type="Black.Sequence.Actor.SequenceActionActorSetStatusInt" path="entities_.qt_ch03_0020_reviathan_last_battle.nodes_.[85].nodes_.[1]" name="[1]" ownerIndex="19" owner="entities_.qt_ch03_0020_reviathan_last_battle.nodes_.[85]">
<Isolated_ type="bool">False</Isolated_>
<in_>
<connections_>
<reference objectIndex="28" reference="True" relativePath="out_" object="entities_.qt_ch03_0020_reviathan_last_battle.nodes_.[85].nodes_.[23]" />
</connections_>
</in_>
<target_ value="10" type="enum">TARGET_PLAYER_NOCTIS</target_>
<kind_ value="789" type="enum">STATUS_KNIGHTS_OF_EOS</kind_>
<value_ type="int">1</value_>
</object>
次に、フォトメニューのどこかに、ビヘイビアを差し込む必要があります。
この動作のトリガーとなるのは、フォトモードが終了したときがよいでしょう。まず、「<CloseMenu>
」(訳注:メニューを閉じる)を検索してください。このトリガーコネクターを見つけることができます。
<CloseMenu dynamic="True" type="SQEX.Ebony.Framework.Node.GraphTriggerInputPin">
<pinName_ type="string">CloseMenu</pinName_>
<connections_>
<reference objectIndex="242" reference="True" relativePath="in_" object="entities_.Ctrl.nodes_.[0].nodes_.[86]" />
<reference objectIndex="253" reference="True" relativePath="in_" object="entities_.Ctrl.nodes_.[0].nodes_.[100]" />
</connections_>
<isBrowsable_ type="bool">True</isBrowsable_>
<delayType_ value="1" type="enum">DT_TIME</delayType_>
<delayTime_ type="float">0</delayTime_>
<delayMaxTime_ type="float">-1</delayMaxTime_>
<pinType_ value="0" type="enum">PT_ARBITRARY</pinType_>
</CloseMenu>
このコネクタは、すでに他の2つのノードに接続していることがわかります。それでいいんです! 好きなだけ接続することができます。
このファイルはゲームから直接取得したものなので、「object 242」へのコネクタはすでにうまく動作していることが分かっています。新しいノードも確実に動作させるために、同じコンテナに配置します。 一番簡単な方法は、「object 242」を見つけて、その下に「覚醒ノクト」ノードを貼り付けることです。
先ほどのリコール。
アトリビュート | 用途 |
---|---|
objectIndex | この番号で <object> を識別する。同じ「objectIndex」を持つ <object> は1つのexmlファイル内に1つしかない。 |
ownerPath | このオブジェクトが含まれるコンテナへのパスである。 |
path | これは <object> 自体へのパスである。 |
name | これは <object> の名前であり、同じコンテナ内の他の <object> と同じであってはならない。 |
ownerIndex | この <object> が含まれるコンテナ <object> の 「objectIndex」である。 |
owner | この <object> が含まれるコンテナ <object> の「path」を指定する。 |
「objectIndex」はユニークでなければならない。ファイルの一番下までスクロールすると、最後の「objectIndex」が345であることに気がつくでしょう。したがって、次の番号である346を「覚醒ノクト」ノードに使用することができます。
「ownerPath」、「ownerIndex」、「owner」は、「object 242」から直接コピーして、同じコンテナ内にあることを確認することができる。
「name」は同じコンテナ内の他のノードと同じであってはならないので、これを確認する必要がある。「ownerIndex」からコンテナが「object 18」であることがわかるので、この <object>
に移動する。かなり大きいので、<nodes_>
が見つかるまで下にスクロールしてください。
<nodes_>
<reference objectIndex="19" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[11]" />
<reference objectIndex="20" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[14]" />
<reference objectIndex="21" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[27]" />
<reference objectIndex="44" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[34]" />
<reference objectIndex="61" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[35]" />
<reference objectIndex="70" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[36]" />
<reference objectIndex="71" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[38]" />
<reference objectIndex="113" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[39]" />
<reference objectIndex="114" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[41]" />
<reference objectIndex="118" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[42]" />
<reference objectIndex="123" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[45]" />
<reference objectIndex="124" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[46]" />
<reference objectIndex="133" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[60]" />
<reference objectIndex="149" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[61]" />
<reference objectIndex="150" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[62]" />
<reference objectIndex="151" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[64]" />
<reference objectIndex="189" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[70]" />
<reference objectIndex="190" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[71]" />
<reference objectIndex="191" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[74]" />
<reference objectIndex="192" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[75]" />
<reference objectIndex="193" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[77]" />
<reference objectIndex="194" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[79]" />
<reference objectIndex="195" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[80]" />
<reference objectIndex="197" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[81]" />
<reference objectIndex="199" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[82]" />
<reference objectIndex="200" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[83]" />
<reference objectIndex="241" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[85]" />
<reference objectIndex="242" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[86]" />
<reference objectIndex="243" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[88]" />
<reference objectIndex="244" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[89]" />
<reference objectIndex="245" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[90]" />
<reference objectIndex="246" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[91]" />
<reference objectIndex="247" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[92]" />
<reference objectIndex="248" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[93]" />
<reference objectIndex="249" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[95]" />
<reference objectIndex="250" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[96]" />
<reference objectIndex="251" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[97]" />
<reference objectIndex="252" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[98]" />
<reference objectIndex="253" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[100]" />
<reference objectIndex="254" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[101]" />
<reference objectIndex="255" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[104]" />
<reference objectIndex="256" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[108]" />
<reference objectIndex="257" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[109]" />
<reference objectIndex="258" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[110]" />
<reference objectIndex="259" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[111]" />
<reference objectIndex="260" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[112]" />
<reference objectIndex="261" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[113]" />
<reference objectIndex="262" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[114]" />
<reference objectIndex="263" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[115]" />
<reference objectIndex="264" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[116]" />
</nodes_>
ここで「object="entities_.Ctrl.nodes_.[0].nodes_.[116]"」を見ると、一番大きな名前が[116]であることがわかると思。したがって、次の論理的名称は[117]となる。
ここにいる間に、新しいノードのコンテナへの参照を追加しておきましょう。
- 既存の参照線をコピー&ペーストする。
- 「objectIndex」を346に変更
- 「object」を「entities_.Ctrl.nodes_.[0].nodes_.[117]」に設定 (最後の部分のみ変更)
はこのように表示されるはずです。
<nodes_>
<reference objectIndex="19" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[11]" />
<reference objectIndex="20" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[14]" />
<reference objectIndex="21" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[27]" />
<reference objectIndex="44" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[34]" />
<reference objectIndex="61" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[35]" />
<reference objectIndex="70" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[36]" />
<reference objectIndex="71" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[38]" />
<reference objectIndex="113" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[39]" />
<reference objectIndex="114" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[41]" />
<reference objectIndex="118" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[42]" />
<reference objectIndex="123" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[45]" />
<reference objectIndex="124" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[46]" />
<reference objectIndex="133" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[60]" />
<reference objectIndex="149" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[61]" />
<reference objectIndex="150" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[62]" />
<reference objectIndex="151" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[64]" />
<reference objectIndex="189" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[70]" />
<reference objectIndex="190" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[71]" />
<reference objectIndex="191" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[74]" />
<reference objectIndex="192" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[75]" />
<reference objectIndex="193" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[77]" />
<reference objectIndex="194" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[79]" />
<reference objectIndex="195" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[80]" />
<reference objectIndex="197" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[81]" />
<reference objectIndex="199" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[82]" />
<reference objectIndex="200" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[83]" />
<reference objectIndex="241" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[85]" />
<reference objectIndex="242" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[86]" />
<reference objectIndex="243" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[88]" />
<reference objectIndex="244" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[89]" />
<reference objectIndex="245" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[90]" />
<reference objectIndex="246" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[91]" />
<reference objectIndex="247" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[92]" />
<reference objectIndex="248" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[93]" />
<reference objectIndex="249" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[95]" />
<reference objectIndex="250" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[96]" />
<reference objectIndex="251" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[97]" />
<reference objectIndex="252" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[98]" />
<reference objectIndex="253" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[100]" />
<reference objectIndex="254" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[101]" />
<reference objectIndex="255" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[104]" />
<reference objectIndex="256" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[108]" />
<reference objectIndex="257" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[109]" />
<reference objectIndex="258" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[110]" />
<reference objectIndex="259" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[111]" />
<reference objectIndex="260" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[112]" />
<reference objectIndex="261" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[113]" />
<reference objectIndex="262" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[114]" />
<reference objectIndex="263" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[115]" />
<reference objectIndex="264" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[116]" />
<reference objectIndex="346" reference="True" object="entities_.Ctrl.nodes_.[0].nodes_.[117]" />
</nodes_>
「覚醒ノクト」ノードに戻ると、「name」は上記で決定した[117]、「path」はコンテナリファレンスで設定したものと同じになっているはずです。
これで「覚醒ノクト」ノードが以下のように表示されるはずです。
<object objectIndex="346" ownerPath="nodes_" checked="True" type="Black.Sequence.Actor.SequenceActionActorSetStatusInt" path="entities_.Ctrl.nodes_.[0].nodes_.[117]" name="[117]" ownerIndex="18" owner="entities_.Ctrl.nodes_.[0]">
<Isolated_ type="bool">False</Isolated_>
<in_>
<connections_>
<reference objectIndex="28" reference="True" relativePath="out_" object="entities_.qt_ch03_0020_reviathan_last_battle.nodes_.[85].nodes_.[23]" />
</connections_>
</in_>
<target_ value="10" type="enum">TARGET_PLAYER_NOCTIS</target_>
<kind_ value="789" type="enum">STATUS_KNIGHTS_OF_EOS</kind_>
<value_ type="int">1</value_>
</object>
このノードがこのファイルに対して正しく更新され、正しいコンテナに配置されたので、最後のステップは、これを「<CloseMenu>
」トリガに接続することです。
まず、「覚醒ノクト」ノードの入力参照を「<CloseMenu>
」コネクタから来るように更新します。 これは、「<CloseMenu>
」からすでに接続されていることが分かっているので、「object 242」からコピーすることができる。
最終的に 「覚醒ノクト」ノードは以下のようになります。
<object objectIndex="346" ownerPath="nodes_" checked="True" type="Black.Sequence.Actor.SequenceActionActorSetStatusInt" path="entities_.Ctrl.nodes_.[0].nodes_.[117]" name="[117]" ownerIndex="18" owner="entities_.Ctrl.nodes_.[0]">
<Isolated_ type="bool">False</Isolated_>
<in_>
<connections_>
<reference objectIndex="18" reference="True" relativePath="triInPorts_.CloseMenu" object="entities_.Ctrl.nodes_.[0]" />
</connections_>
</in_>
<target_ value="10" type="enum">TARGET_PLAYER_NOCTIS</target_>
<kind_ value="789" type="enum">STATUS_KNIGHTS_OF_EOS</kind_>
<value_ type="int">1</value_>
</object>
接続は両端で行わなければならないことを忘れないでください。
「<CloseMenu>
」 "に戻り、「object 242」への参照のコピーを作成します。
再度、「objectIndex」を346に、「object」を[117]に変更します。
最終的な「<CloseMenu>
」の結果は以下の通りです。
<CloseMenu dynamic="True" type="SQEX.Ebony.Framework.Node.GraphTriggerInputPin">
<pinName_ type="string">CloseMenu</pinName_>
<connections_>
<reference objectIndex="242" reference="True" relativePath="in_" object="entities_.Ctrl.nodes_.[0].nodes_.[86]" />
<reference objectIndex="346" reference="True" relativePath="in_" object="entities_.Ctrl.nodes_.[0].nodes_.[117]" />
<reference objectIndex="253" reference="True" relativePath="in_" object="entities_.Ctrl.nodes_.[0].nodes_.[100]" />
</connections_>
<isBrowsable_ type="bool">True</isBrowsable_>
<delayType_ value="1" type="enum">DT_TIME</delayType_>
<delayTime_ type="float">0</delayTime_>
<delayMaxTime_ type="float">-1</delayMaxTime_>
<pinType_ value="0" type="enum">PT_ARBITRARY</pinType_>
</CloseMenu>
これでMODは完成です。ゲームに適用すると、カメラを開いてから再び閉じると「覚醒ノクト」モードが有効になるはずです。
exmlの編集が終わり、MODをゲームに入れる場合は、Flagrumを使って非常に簡単に行うことができます。
- 新しいMODを作成する。
- MODの詳細を設定する。
- 元の exml ファイルを編集したものと置き換えます。
- MODを保存する。これでMODがビルドされ、ゲームに適用されます。
MOD作成後にexmlファイルを変更する場合は、先にexmlファイルへの変更を保存してください。
次に、この画面に戻り、再度保存ボタンをクリックして、新しい変更内容でMODを再構築します。
- (オプション)MODを配布するために梱包します。