[ITG]StepMania5.1のxml→lua自動変換機能について②(難易度に応じた動作変更の実装)

記事の目的

前回の記事([ITG]StepMania5.1のxml→lua自動変換機能について①(使用方法) - kaiの日記)にて、xml2luaによる自動変換の使い方を解説しました。
またその中で、難易度に応じたジャケット分岐(Lua講座第2回の内容)については自動変換が上手くいかなかったことを述べました。

この記事では、なぜ変換が上手くいかなかったか、デバックの結果わかった内容(ハマりポイント)を共有します。
また、ハマりポイントを回避する方法を紹介し、SM5でどのように実装すべきかの一例を示します。

lua

変換元のlua(OpenITG向け)


自動変換したlua


修正したlua(SM5向け)

解説

デバッグの結果わかったのは以下の3点でした。


 ①GetDifficulty()で数値ではなくDifficulty_Hardのような文字列が返る
GetDifficulty()で難易度を取得した際に、OpenITGでは0~5の数値が返るのですが、StepMania5系では”Difficulty_Hard”のような文字列が返ることがデバッグの結果わかりました。どうして


解決方法はいくつか考えられるのですが、ここでは元の実装を流用するため、Difficulty_Hardのような文字列を数値に変換する方法を考えます。


結論としては以下です。

(OpenITG系の実装)
difficulty1P = GAMESTATE:GetCurrentSteps(PLAYER_1):GetDifficulty()


(StepMania5系の実装)
d = Enum.Reverse( Difficulty );
difficulty1P = d[GAMESTATE:GetCurrentSteps(PLAYER_1):GetDifficulty()];


StepMania5.0系ではEnumsの中でDifficulty_Hard等のインデックスと難易度数値の紐付きが定義されています。
f:id:kai_yuki:20200324223452p:plain

Enum.Reverse()はそのテーブル(文字列→数値)を返す関数です。
SM5 for lua(URLは記事の末尾に記載)では” Returns a reverse lookup table”と解説されており、関数名もreverseが付いていますので「逆引き」となりますが、DNSの逆引きとは意味が異なるので注意が必要かもしれません。
1行目でdにテーブルが格納されるので、あとは変数に代入しているだけです。


d = Enum.Reverse( Difficulty );については逆引きテーブルの配列を代入しているだけなので1回宣言すればOKです。
また、変数名(上記ではd)は何でもよいです。


②Conditionが関数に変換される
自動変換するとConditionの部分がoptional_actor(cond, actor)という関数に変換されます。
条件に合致すればactorを返し、合致しなければ空のactorを返す(何もしない)という関数のようです。


自動変換されるということは、てっきりStepMania5系ではCondition命令が無いのかと思っていました。
実際はSM5系でもCondition命令は存在しますし、動作も下記③で述べる判定タイミングの問題以外はOpenITG系と同じように動きます。どうして
そのため、Condition命令を使うように書き直しました。(下記③の理由で最終的には採用せず)


ちなみに、怒首領Papasitoのluaで、難易度に応じて演出を変える(MOD無し/大往生/デスレーベル)部分についてはConditionを用いた実装でSM5対応をしていますので、興味があればluaの中身を見て確認してもらえればと思います。
参考:[ITG] フメンタイン2020投稿譜面について - kaiの日記


③Conditionの判定タイミングが早い
以前の記事([ITG] Lua講座(第1回) ランダムでMVを分岐させる – SPACE OF SOUL - kaiの日記)でConditionの判定タイミングがInitCommandより早いことは書きましたが、SM5系では本当に早くて、簡単な計算でも間に合っていないことがデバッグの結果わかりました。


今回は判定条件がやや複雑で、かつ3レイヤで同じ判定条件を使うことから、difficultyを計算する部分をまるごとConditionに突っ込むのはやめました。
Conditionを使わず、OnCommand内で条件に合致した場合のみ表示(self:diffusealpha(1))する実装に変えました。


以上①②③を踏まえて修正したのが上記のluaです。


SM5系はOpenITGと違って、luaが間違っていても本体ごと落ちるということがなく、エラーも吐かずただただ動かないだけなので切り分けには苦労しました。
デバッグには下記のメッセージ表示コマンドが役立ちました。

SCREENMAN:SystemMessage(文字列)

画面の左上の方に表示されます。

例えば、difficultyの数値を表示する場合は
SCREENMAN:SystemMessage(tostring(difficulty))
です。

参考URL

Lua for StepMania 5
https://quietly-turning.github.io/Lua-For-SM5/
StepMania5版のlua解説サイト(英語)です。使用できる関数や3.9系との違いなど、SM5系のluaを作成するのに必要な情報が詰まっています。
今回のデバッグ(特に①②の解決)にも上記ページの解説が役に立ちました。


paraphrohn’s diary ITGギミック制作記6: StepMania5への対応 (1)
https://paraphrohn.hateblo.jp/entry/2019/09/15/212958
xmlluaの構文の違いについての解説があります。xml2luaの自動変換は、この記事で記載されている内容の置換+αを自動でやってくれるイメージです。