2015年1月17日土曜日

[Modding]手探りで作成するシンプルなMOD



今回は、なんとなく思い付きでMODを作成してみよう、と思ったものの
結局手探りで四苦八苦したので記録に残しておこう、という記事になります。

わからないところは読み飛ばす、という雑な方法でやっていますので
成功はしましたが、動作・仕様的に正しいものかどうかは分かりません。
あくまで参考程度にとどめておいてください。

※xmlを解析しているのでネタバレにご注意ください。

(2015/10/15 新仕様ベースに改訂)


今回作成するMOD

今回は、MODとしては最もシンプルな"アイテムの実装"に挑戦してみます。
NEO Scavenger本体にも、サンプルとしてMODのテンプレート的なものがありますが、
Cryoに名前の違う袋が出てくるだけです。(※確認はしていません)

それでは面白くないので、今回はちょっと頑張って、
新規画像を使った装備品を用意してみます。

MODの仕様は以下のように決定しました。

1.頭に被れるゆっくりのマスクを追加する
2.被った時に何らかの効果が出るようにする
3.マスクを任意の場所に1つだけ配置する

あくまでサンプルなので、動作確認用の最小単位で実装します。
では、順を追ってMODを作成していきます。


画像を用意する

画像を用意するとして、どんなものが必要かを確認しなければいけません。
そこで、同じマスクである"Clown Head"を参考にしてみました。
imgフォルダをClownHeadという名前で検索してみた結果、
以下の5つが見つかりました。

CreItmClownHead.png … マップや戦闘画面で表示されるスプライト
ItmClownHead.png … (Small GUI)装備時のグラフィック
ItmClownHeadStored.png … (Small GUI)インベントリでのグラフィック
x2_ItmClownHead.png … (Big GUI)装備時のグラフィック
x2_ItmClownHeadStored.png … (Big GUI)インベントリでのグラフィック


x2系の画像は元画像を拡大すれば流用できますので、
まずは画像を3枚用意します。




(※質に関しては中の人の限界です。ご了承ください。)
ここで重要なのは、背景の透過を忘れずにしておくことと、
マップでの表示スプライトや装備時のグラフィックは
体全体分のスペースで正しい位置に配置する必要がある、ということですが
今回はClownHeadの画像をリネーム・流用しています。


アイテムの仕様を決定する

では、ここで改めてアイテムの仕様を決定します。
考えるべきなのは、このMODで"何を実装するか"ということです。
先ほどのリストを元に考えると、

1.はアイテムとしてのゆっくりマスク
2.はマスクをつけたときの効果
3.は確認さえできればいいので、
Cryoの初期配置アイテムに追加することにします。

つまり、1と2は新規に追加する項目で、
3は既存のデータを上書きする必要があります。


MOD用に環境・フォルダを作成する

NEO ScavengerのMODのサンプルでは、
データは新規に追加されるものと上書きされるものに分けられています。
追加されるデータはSampleModFolderというフォルダに、
上書きされるものは0(ゼロ)という名前のフォルダに記述します。

(※この0という名前は特別なもので、
ゲーム本体のデータを示すものとして使うようです)

今回作成するMODもこれを参考にして作成します。


まずは、今回のMODで追加するデータから用意します。
最初にyukkuri_headというフォルダ(名前は任意)を用意し、
その中にimgフォルダを作成して、追加する画像5枚をコピーします。

同様にdataフォルダを作成して、itemtypes.xmlとconditions.xmlを作成し、
それぞれ先頭から<database name="neogame">というタグまでと、
</database>というタグから末尾までを元のxmlからコピーします。
(tableタグのない状態のxmlを用意しています)

また、getimages.phpを作成し、yukkuri_headフォルダ直下に置いておきます。

用意した画像を読み込ませるためにgetimages.phpを改変します。
中身は他のMODを参考にして記述しています。
nRows=5&nCols=2
&strImageURL0=CreItmYukkuriHead.png
&strImageURL1=ItmYukkuriHead.png
&strImageURL2=ItmYukkuriHeadStored.png
&strImageURL3=x2_ItmYukkuriHead.png
&strImageURL4=x2_ItmYukkuriHeadStored.png
nRowsは画像の数と合わせておいてください。
nColsは2にしておけば問題ないはずです。


次は既存データの上書きに必要な部分です。
0というフォルダを作成し、SampleModFolderからgetimages.phpをコピーします。
こちらのgetimages.phpは改変の必要がないので、サンプルのものを流用しています。

同じくdataフォルダを作成し、treasuretable.xmlを作成します。
これも同様に、先頭から<database name="neogame">というタグまでと、
</database>というタグから末尾までを元のxmlからコピーします。
次に、exeファイルと同じフォルダに配置するgetmods.phpを作成します。
これは、MODのロード順を記述するもので、
今回はサンプルとして用意されたgetmods.example.phpを改変しています。
中身は以下の通り。
nRows=2
&strModName0=YukkuriHead&strModURL0=yukkuri_head
&strModName1=0&strModURL1=0
strModNameには任意のMOD名を記述します。
後で使うので、とりあえずYukkuriHeadとしておきました。

strModURLのほうはフォルダ名です。
もちろんさきほど作成したyukkuri_headというフォルダ名が入ります。
MOD名と被るとややこしいので、基本的に別の名前を使うようにしています。


新規追加分のデータを記述する

まず新規追加分として必要なデータは、
アイテム本体、つまり"itmtypes"というテーブルで記述されているものです。
このテーブルは、同じ名前のitemtypes.xmlに記述されています。

これはClownHeadのものを流用し、必要な部分だけ改変します。
特に改変が必要なのは、id,nGroupID,nSubgroupID
strDescカーソルを合わせたときに出る名前)、
vImageList、vSpriteList使用する画像の名前)、
aEquipConditions装備時に発生する効果、スロット=conditionのID)あたりだと思います。

詳細は、実際のデータを見ながら説明していきます。
すべてを理解しているわけではないので、変更した部分のみ補足します。

<table name="itemtypes">
            <column name="id">999</column>
            <column name="nGroupID">200</column>
            <column name="nSubgroupID">0</column>
idとGroupIDは、テスト用なのでとりあえず被らない数値にしてあります。
idはtable nameごとに0か1あたりから付けられているはずなので、
大量にデータを追加するときは、実際に使われていないIDを順に付けていけば問題ないはずです。
SubgroupIDはGroupIDとセットで使用されるもののようなので、
今回は特に気にせず0にしています。
            <column name="strName">headwear</column>
            <column name="strDesc">yukkuri head</column>
アイテム名をここで記述しています。
            <column name="strDescAlt"></column>
            <column name="nCondID">0:1</column>
このID自体は変更していませんが、頭に0:を付けています。
元のデータのものを参照するときは、これを付けないとエラーが出るようです。
以降、0:の付いたものは同じ理由で改変したものです。
            <column name="vImageList">ItmYukkuriHead.png,ItmYukkuriHeadStored.png</column>
アイテム画像名はここで記述します。x2はおそらく自動で判別してくれるのかもしれません
            <column name="vSpriteList">17=CreItmYukkuriHead.png</column>
こちらがマップで表示される画像です。
            <column name="vImageUsage">1,1,0,0,1,1</column>
            <column name="fWeight">0.44</column>
            <column name="fMonetaryValue">2</column>
            <column name="fMonetaryValueAlt">0</column>
            <column name="fDurability">1</column>
            <column name="fDegradePerHour">0</column>
            <column name="fEquipDegradePerHour">0.0001</column>
            <column name="fDegradePerUse">0</column>
            <column name="vDegradeTreasureIDs">0:3,0:3</column>
            <column name="aEquipConditions">17=999</column>
ここで、装備した時の効果を設定しています。
17が頭スロットを表すもので、頭に装備した時にID999番の効果が発生します。
これは新規追加分なので0:は使用しません。
            <column name="aPossessConditions"></column>
            <column name="aUseConditions"></column>
            <column name="aCapacities"></column>
            <column name="vEquipSlots">17=0=0,20,21</column>
            <column name="vUseSlots"></column>
            <column name="bSocketLocked">0</column>
            <column name="vProperties">0:9,0:10,0:16,0:28,0:48,0:50</column>
            <column name="aContentIDs"></column>
            <column name="nFormatID">0:3</column>
            <column name="nTreasureID">0:0</column>
            <column name="nComponentID">0:3</column>
            <column name="bMirrored">0</column>
            <column name="nSlotDepth">2</column>
            <column name="strChargeProfiles"></column>
            <column name="aAttackModes"></column>
            <column name="nStackLimit">1</column>
            <column name="aSwitchIDs"></column>
            <column name="aSounds">0:cueClownHeadPickup,0:cueClownHeadPutdown2</column>
        </table>
次に、追加効果の方を設定します。
参照するテーブルは"conditions"で、conditions.xmlに記述されます。
今回は分かりやすいdogman fur coatの装備効果を流用します。

<table name="conditions">
            <column name="id">999</column>
IDはitmtypesのほうで記述していますが、999を使用します。
            <column name="strName">Wearing yukkuri mask</column>
            <column name="strDesc">&lt;us&gt; is wearing yukkuri mask, makes wearer lil' horrible.</column>
名前と効果の説明は適当に付けています。
            <column name="aFieldNames">m_fMorale</column>
            <column name="aModifiers">0.8</column>
この2行が効果の本体で、m_fMoraleを0.8上昇させています。
効果を分かりやすくするために大きめの値にしていますが、元の値は0.3程度でした。
            <column name="aEffects">ArmorWound=100,1,0.4;</column>
ここはおそらく装備品としての防御力が設定されているので、
ここだけClownHeadのものを流用しています。
            <column name="bFatal">0</column>
            <column name="vIDNext">0</column>
            <column name="fDuration">0</column>
            <column name="bPermanent">0</column>
            <column name="vChanceNext">0</column>
            <column name="bStackable">0</column>
            <column name="bDisplay">1</column>
            <column name="bDisplayOther">1</column>
            <column name="bDisplayGameOver">1</column>
            <column name="nColor">2</column>
            <column name="bResetTimer">1</column>
            <column name="bRemoveAll">0</column>
            <column name="bRemovePostCombat">0</column>
            <column name="nTransferRange">-1</column>
            <column name="aThresholds"></column>
        </table>
これで、着けている間は威嚇効果(たぶん)が発生する、
yukkuri headというアイテムが実装されました。



上書きするデータを探して記述する

あと必要なのは、実装したアイテムをどこで手に入れるか、という設定です。
今回はCryoの初期配置に追加するので、
treasuretable.xmlにある、"treasuretable"テーブルのID164番を改変します。


<table name="treasuretable">
            <column name="id">164</column>
            <column name="strName">cryo idle loot</column>
            <column name="aTreasures">YukkuriHead:200.0x1x1-1,0.0x0x1-1,86.6x1.0x5-9</column>
            <column name="bNested">0</column>
            <column name="bSuppress">0</column>
            <column name="bIdentify">0</column>
       </table>

改変したのはaTreasuresの部分だけですが、
この記述方法が分かりづらいので、ここで解説します。
書かれたデータは","で区切られた2つの文字列で、
後半部分の"86.6x1.0x5-9"を例に説明すると、

GroupIDが86SubgroupIDが6のアイテム、つまりshard
確率1.0、つまり100%の確率で、5-9個配置する、というものです。

ここで前半の部分に戻って説明すると、
頭のYukkuriHeadMOD名で、別のフォルダなのでこれで参照しています。
200,0はアイテムのyukkuri headに設定したGroupIDとSubgroupIDで、
これも100%配置、個数は1個に固定しています。

つまり、yukkuri headが必ずCryoに1個配置されていることになります。

(2015/1/18追記)今回はアイテムをIDで参照する方法を挙げましたが、
別の"treasuretable"テーブルを参照することも出来ます。
詳しくは別の機会に、"treasuretable"テーブルの解析と言う形で行います。


動作を確認する

まずは、テスト環境としてNEO Scavenger本体をコピーしたものを用意しておきます。
配布前提のMODなら、テストは手を加えていない環境で行いましょう。

MODのテストを行うには、作成したデータをテスト環境に上書きします。
このとき、0フォルダの中身はサンプル用MODのデータが入っているため、
念のため0フォルダを削除してからコピーするようにしましょう。
getmods.phpはそのまま上書きして構いません。

では、以上のデータをテスト環境に配置して、本体を起動してみます。
このとき、データの読み込みから先に進まない場合は、
"0:"を使ったID参照が不十分である可能性があります。


こんな感じにCryoに1つだけ配置されます。
Conditionはランダムですが、ZomZom'sのように100%で配置することも出来そうです。


被るとこんな感じです。位置調整が雑だったのでちょっとずれています。


で、肝心のMorale上昇効果を検証してみた結果、
武器装備Bad Muthaに素手でSurrender→効かず
少し怪我させてからSurrender→効かず
さらにdogman coatも着てSurrender→降参
という感じですが、ランダム性があるかどうかは未調査です。


やっつけで作った性能ですが、性能としてはそこそこチート級に仕上がった気がします。

まとめ

というわけで、今回のMODはそこそこ想定通りに作成できました。
画像さえ用意すれば大体のものは作れてしまう…はずなので、
次回以降はそういった要素ごとに"どうすれば実装できるか"を検証していきます。

0 件のコメント:

コメントを投稿