Noitaで重音テトmodをつくる

投稿日 最終更新日

2025年05月31日

Noitaという激おもろゲームがあるんだけど、modを作ったので簡単な作り方なども含めて残しておく。

作ったmodはAngry Tetoという一緒に戦ってくれるアングリーゴーストの見た目を重音テトにリプレイスするもの。 angry_teto.gif

既にメインキャラを初音ミクに変える素晴らしいmodは存在していて、あとは重音テトとも一緒に戦えたら嬉しいよねという理由で。

前提

  • Windows環境の話です
  • PCでのプログラミング経験がある前提で話しています
  • 私は今回使うluaというプログラミング言語も、Noitaのmod作成も未経験でしたので未熟な部分あると思われます

公式のドキュメントと利用許諾書を読む

Noitaをインストールすると、インストールしたNoitaフォルダ内に Noita\tools_moddingのようにtools_moddingフォルダができている。

これが公式の用意しているドキュメント群で、公式情報をみたい場合は主にここを参照することになる。

以下は読むことが必須

  • READ_ME_FIRST.txt
  • Noita-ModdingAgreement-vXXX.rtf: Mod同意書

また、以下のファイル/フォルダも必要に応じて読むと良さげ

  • component_documentation.txt
    • 各コンポーネントのメンバ変数とかその説明とかが書いてある
  • lua_api_documentation.html
    • Noitaの提供するAPIの一覧が書いてある
  • lua_debugging.txt
    • Luaのデバッグ方法について書いてある
  • noita-fmod-projectフォルダ
    • 音をいじりたい場合はこのフォルダ内を参照する必要あり

Mod作成の環境構築まで

恐らく、Lua言語をいじるのであればDecodaというIDEが良いのだけど、今回は大規模なModを作成するわけでないのでVSCodeを利用する。

Gitとかは説明しないけど、使った方が良いので適当なところで各自でやってもらう感じで。

dataフォルダを生成する

dataというModを作りやすくするためにNoitaが分離してくれたフォルダがある。

このdataフォルダ内にMod製作者が弄りたいであろうファイルが管理されていて、これ等を上書きする形でプログラムや見た目を簡単に改造できるようになっている感じ。

以下の手順でdataフォルダを生成する

  1. Noita\tools_moddingの中身をNoitaフォルダに全てコピペ
  2. data_wak_unpack.batを実行 こうすると私の場合はAppData\LocalLow\Nolla_Games_Noita\dataにdataフォルダが生成された。

modを構築するフォルダを作る

`Noita\mods\に好きな名前でフォルダを作る。

今回私の場合はだとNoita\mods\angry_teto\のような感じでフォルダを作成した。

Modを制作する

作成したmod構築用フォルダをVSCodeやらで開いて、作業していく。

また、modの具体的な構築例をみたい場合は公式のmodで既に用意されている

  • Noita\mods\example
  • Noita\mods\nightmare を参考にすると良い。 もし、具体的に制作したいmodがあり、それに似たModが既に配布されているのであれば、その配布されているModを参照するのも大いにあり。

mod.xmlを作成する

Modを読み込むのに必須なファイルであるmod.xmlを作成する。

もしかしたらバージョンによって中身が変わるかもなので、具体的な例はNoita\mods\example\mod.xmlを参照するのが良いと思われる。

私の場合は以下

<Mod
	name="Angry Teto"
	description="Changes Angry Ghost to Angry Teto"
	request_no_api_restrictions="0"
>
</Mod>

request_no_api_restrictionsは、基本的にmodでの利用が禁止されているLuaAPIを利用したい場合のみ1にする。 1にすると自由度が増す代わりに、ワークショップで配布できなくなるので注意。

リスポーン時にangry_ghostパークを所持する部分を作る

今回作るmodはパークangry_ghostの見た目を変えるmodなので、初期リスポーン時にこのパークを所持しておきたい。

丁度、Steamのワークショップで一番人気のあるmodのEdit Wands Alwaysを参考にすれば良さそう。

ワークショップのmodは以下の手順でフォルダを閲覧できる

  • 該当modをワークショップからサブスクライブ
  • 該当modのIDをURLとかから確認する
  • Noitaが入っているディスク\SteamLibrary\steamapps\workshop\content\881100\該当modのIDがそのmodフォルダ
    • 881100がNoitaのゲームID
    • Edit Wands AlwaysのIDは2182627060

Edit Wands Alwaysのmodフォルダを開くと何個かファイルが存在するけど、大事なのは

  • init.lua
  • files/remove.lua の2つだけなので、安心。

init.lua

コード見せたほうが早いと思うので見せる。 以下のような感じで最初からangry_ghostを所持している。

dofile_once( "data/scripts/lib/utilities.lua" )
dofile_once( "data/scripts/perks/perk_list.lua" )

-- リスポーン時の実行関数
function OnPlayerSpawned(player_entity)
	-- 複数回実行されないようにフラグ管理
    if GameHasFlagRun("angry_teto_already_run") then
        return
    end
    GameAddFlagRun("angry_teto_already_run")

    local perk_id  = "ANGRY_GHOST"
    local perk_data = get_perk_with_id(perk_list, perk_id)

	-- 恐らく必要なフラグ建て(Edit Wands Alwaysにあったのでそのまま流用)
    GameAddFlagRun( get_perk_picked_flag_name(perk_id) )

	-- アングリーゴーストを出現させる関数の実行
    perk_data.func( nil, player_entity, nil )

	-- 取得パーク一覧に追加
    local ui = EntityCreateNew( "" )
    EntityAddComponent( ui, "UIIconComponent",
    EntityAddComponent( ui, "UIIconComponent",
        {
            name              = perk_data.ui_name,
            description       = perk_data.ui_description,
            icon_sprite_file  = perk_data.ui_icon
        }
    )
    EntityAddChild( player_entity, ui )
end

OnPlayerSpawned(), GameHasFlagRun(), perk_data.func()とかどこで定義されてんの? っていう関数がいっぱい出てくるんだけど、マジで頑張って探すしかないっぽい。

ただ、今回はEdit Wands Alwaysのコードを参考にしているのである程度何の関数が必要で、それがどこに定義されているのかあたりを付けられる感じ。 OnPlayerSpawned()とかは公式modであるexampleのinit.luaに書いてあったりする。 GameHasFlagRun()lua_api_documentation.htmlに説明ある。 UIIconComponentcomponent_documentation.txtに説明ある。

どこに説明がなくても、dataフォルダ内に大体処理はあるので全ファイル探索とかすればどうにかはなりそう。

見た目を変える

今回はangry_ghostの見た目を変えたいので以下のファイルを上書きする形になる

  • data\items_gfx\perks\angry_ghost.png
    • パークのアイコン
  • data\projectiles_gfx\angry_ghost.png
    • angry_ghostの見た目部分のスプライト
  • data\ui_gfx\perk_icons\angry_ghost.png
    • UIのアイコン

この3つを自分のmodフォルダ内に作る。 つまり以下のような感じ

.
|-- data
|   |-- items_gfx
|   |   `-- perks
|   |       `-- angry_ghost.png
|   |-- projectiles_gfx
|   |   `-- angry_ghost.png
|   `-- ui_gfx
|       `-- perk_icons
|           `-- angry_ghost.png
|-- init.lua
`-- mod.xml

ここはもう気合で元絵を参考にドット絵を描くしかない。

ドットの数がそのままNoita内での大きさになるので、注意。 そのため、アイコン系は元画像と同じピクセル数が良い。

スプライト部分は元画像が8x8を1フレームとするスプライトでも、xmlで

  • 特定のアクションを何フレームにするか
  • 1フレームを何ピクセルx何ピクセルにするか 等を決められる。

ただ、どちらにしろ画像の大きさ=ゲーム内での大きさなのは注意。

XMLを調整する

私の場合、スプライトの1フレームの大きさが10x933x31と3倍くらいに大きくなったのでXMLをいじらないと正常に表示されない。

今回の場合は以下のファイルをいじる形になる

  • data\entities\misc\perks\angry_ghost.xml
  • data\projectiles_gfx\angry_ghost.xml

例えば、data\projectiles_gfx\angry_ghost.xmlでは以下のようにAnimation毎にスプライトの適用方法を定めていたり、offsetの指定があったりするので自分の画像の大きさに合わせる。

 <Sprite 
   default_animation="float_right" 
   filename="data/projectiles_gfx/angry_ghost.png" 
-  offset_x="4.5" 
-  offset_y="5" >
+  offset_x="15.5" 
+  offset_y="16.5" >
 
   <RectAnimation 
     name="float_right" 
     frame_count="8" 
-    frame_height="10" 
+    frame_height="33" 
     frame_wait="0.14" 
-    frame_width="9" 
-    frames_per_row="12" 
+    frame_width="31" 
+    frames_per_row="8" 
     pos_x="0" 
     pos_y="0" >
   </RectAnimation>
...

このRectAnimationでは

  • name: アニメーションの名前
  • frame_count: 何フレームのアニメーションか
  • frame_height: 1フレームあたりの高さ
  • frame_wait: 1フレームあたりの長さ
  • frame_width: 1フレームあたりの横幅
  • frames_per_row: スプライト上で1行に並んでいるフレームの数
  • pos_x, pos_y: スプライト画像内での開始位置 が決まっているっぽい。

他にもdata\entities\misc\perks\angry_ghost.xml

 <Entity tags="angry_ghost" >
 	<HitboxComponent 
         _tags="enabled_in_world"
-        aabb_min_x="-4" 
-        aabb_max_x="4" 
-        aabb_min_y="-3" 
-        aabb_max_y="3"
+        aabb_min_x="-16" 
+        aabb_max_x="16" 
+        aabb_min_y="-17" 
+        aabb_max_y="17"
     ></HitboxComponent>

のようにヒットボックスを調整して完了。

ModをWorkShopで公開する

NoitaはWorkShopでModを世界へ共有できるので、やってみよう。

workshop.xmlをつくる

MODフォルダ内に workshop.xml というファイルを作成して説明文を書く

    <Mod
        name="YOUR_MOD_NAME_HERE"
        description="YOUR_MOD_DESCRIPTION_HERE"
        tags="TAGS"
        dont_upload_folders="FOLDER_TO_IGNORE1|FOLDER_TO_IGNORE2"
        dont_upload_files="FILE_TO_IGNORE1|FILE_TO_IGNORE2"
    > 
    </Mod>

tagsは記事書いている時点で

        gameplay
        graphics
        quality of life
        translations
        perks
        spells
        player characters
        loadouts
        biomes
        total conversions
        game modes
        creatures
        bosses
        alchemy
        tweaks
        items
        audio
        cheats
        funny
        streaming integration
        mod dependencies

の中から複数選べる感じ。

私は以下のような感じで設定

<Mod
    name="Angry Teto"
    description="Changes Angry Ghost to Angry Teto"
    tags="graphics,funny"
    dont_upload_folders="assets_dev"
>
</Mod>
  • .gitフォルダはデフォで無視されるっぽいので記述いらない
  • 画像の編集で使ったGIMPのファイルとかをassets_devフォルダでgit管理するので、dont_upload_folders=に入れた感じ

workshop_preview_image.pngをつくる

いわゆるサムネ画像を16:9で作成する。

他の人のサムネを見ると、Noita特有のフォントを使ってるのが多かった。 どうしてるんだろうと思ったらredditで個人の方が配布しているっぽい。 ありがたく使わせていただく。

最終的に以下のようなサムネにした。 workshop_preview_image.webp

アップロード

実際にここまで作ったら、Noita/

.\noita_dev.exe -workshop_upload

を実行。

実行すると以下のようにコマンドプロンプトで対話方式のアップロードが始まる。

----------------------------------------------
Modding Noita is only allowed if you agree to the Modding Agreement.
The Modding Agreement can be found in the tools_modding folder shipped along with the game.
Uploaded mods will be hidden until you have agreed the Steam Workshop Legal Agreement.
----------------------------------------------

Mods available for upload:
   angry_teto
Please type the name of the mod to upload to Steam Workshop and press [ENTER]:
angry_teto
Please type change notes (for example "First release", use '\n' for newline) and press [ENTER]:
First release

Name:         Angry Teto
Description:  Changes Angry Ghost to Angry Teto
Tags:         graphics,funny
Change notes: First release
Above info will appear in Steam Workshop. Does it look OK? [y/n]: y
...
Uploading...
Done!

Done!でアップロード完了。

誰でも使えるようになるよ。

以上です。