takashiskiのブログ

覚書の殴り書き

Noitaの杖の定義を読んでみる

Steamで人気?のNolla gamesのNoitaのコード読みます。

今回読むのは、杖の定義です。

具体的には、NoitaのModを使うための手順だったかで「これをルートフォルダに移動して実行しろ!」とか書いてあるファイルを実行したときに展開されるファイル群の中に入っているdata/entities/items/wands/wand_good_1*です。

事前知識

  • 何故か内部定義ではwandではなくgunが使われているようです。もともとはそういうあれだったのかもしれません。
  • コードの記述され方がバラバラです。グローバル領域にべた書きされている部分もあれば、関数でくるんで定義直後で関数呼び出ししているものもあります。
  • どこからでも呼べるAPI関数はパスカルケースのようです。使い捨てな関数はスネークケースのようです。 また、変数名はスネークケースなようです。
  • 基本的にLuaスクリプトを書くことで世界を制御できます

XML

杖の読み込みはXMLをEntityLoadで読み込むことで完了します。まずXMLを読みましょう。

  • Entity
    • AbilityComponent
      • gun_config
      • gunaction_config
    • HotspotComponent
    • Base
      • ItemComponent
      • SpriteComponent
      • SimplePhysicsComponent
    • LuaComponent
    • ManaReloaderComponent
    • LuaComponent(2個目)

なんとなーく名前からわかる気もしますが、ぱっと見ただけではよくわかりません。

ほかのファイルとの関係をみる

同じフォルダには、同名の拡張子違いのファイルがありました。 それらのファイルとの関係性を探ることで何かつかめる気がします。

その視点から見ると、いくらか他のファイルへの参照を持っている要素があります。

  • AbilityComponent
  • Base
  • SpriteComponent
  • LuaComponent
  • LuaComponent(2個目)

このうち、AbilityComponentとSpriteComponentは同じwand_good_1_sprite.xmlへの参照を持っています。

Baseはbase_item.xmlなので名前から素直に考えると、雛形的な何かのようです。 ちらっとみてみたところ、物理演算廻りの数値や当たり判定、光源や音などが定義されているようでした。

残る二つはLuaファイルへの参照を持っています。 1個目はwand_good_1.lua, 2個目はwand_good_pickup.luaです。

基本的にはModはLuaで書かれることになっているはずですので、見ていきましょう。

lua(wand_good_1.lua)

外部ファイル読み込み

dofileは外部ファイル読み込みです。noitaでは関数やテーブルが定義されているファイルを読み込むために使われることが多いです。

必要なら後から読みに行きましょう。

あとdofile_onceがnoitaで定義されて現在ではそちらが推奨されているようです。

関数定義

functionから始まるのは関数定義です。

これらは杖の内容をランダムにしたいときに使う便利関数のようです。

実際の処理

localがローカル変数の定義で、ここからがこのファイルの処理内容のようです。

おそらく最新の==使用されていないEntityIdを取得します。 このEntityIdの位置情報を乱数のシードに使います。

XMLのAbilityComponentをTableとして取得します。

そのあとに杖の能力を定義しています。振れ幅を持ちたい数値は、{下限,上限}や候補などの形で保持しています。

最後に、XMLで定義されていたオブジェクトたちに対して値を代入していきます。

ComponentSetValueは今回はAbilityComponentの要素として、ComponentObjectSetValueはAbilityComponentの子要素の要素として値を代入する関数のようです。

最後のAddGunActionは杖が持っている呪文を定義する関数です。 コメントアウトされているAddGunActionPermanentを代わりにつかうと、永続呪文として定義されます。

Lua

Luaスクリプトの中身は以下の要素から構成されていました。

  • (便利関数定義)
  • AbilityComponentをテーブルとして読みだす
  • 杖のパラメータをAbilityComponentのテーブルに代入する

Lua(wand_good_pickup.lua)

2個目のLuaスクリプトのwand_good_pickup.luaを読みます。このファイルは1関数が定義されているようです。

通常アイテムの取得処理はEntityAddChild()を使ってインベントリーエンティティに対してアイテムを追加します。

どうやらこの関数はワールド内にこの杖が一つしかない状態にしたいようです。 内部に取得処理は特に書かれていないようにみえます(entity_who_pickedが引数にはあるけど使われていない?)。

とりあえず杖の存在の性質(ユニークアイテム)には影響を与えそうですが、杖の能力自体には影響がなさそうなので無視してよさそうです。

まとめ

以下のことが分かりました。

最初は適当な杖のXML定義を改造して、何をしてよいのか探るのがよさそうです(Mod内でエラーがあっても握りつぶされます)。

次は、初期杖を変更するModを書く話をします。