SetWaitModeはその実、何をwaitしているのか？

そもそも私がこの記事を書こうと思ったのは、公式フォーラムで見たとある質問が切っ掛けになっております。

◆スクリプト：$gameMessage.add('aaaa');
：　　　　　：this.setWaitMode('message');
◆スクリプト：AudioManager.playSe({name:'Attack1', volume:90, pitch:100, pan:0})

↓

何故スクリプトを分けるとsetWaitModeが機能するのかさっぱり分かりませんが、とにかくありがとうございました。

(https://forum.tkool.jp/index.php?threads/%E3%80%90%E8%A7%A3%E6%B1%BA%E6%B8%88%E3%81%BF%E3%80%91-gamemessage-add-%E3%81%A7%E5%81%9C%E6%AD%A2%E3%81%95%E3%81%9B%E3%82%8B%E6%96%B9%E6%B3%95.3422/#post-18405)



ここら辺の仕組み、あまり解説している所ないよな…
しかも、これってツクールの根幹を理解するのに良い機会だよな…
と考え、この記事を建てました。


#そもツクールMVはどうやって「動いて」いるのか？
大元を辿れば、メインとなるループは`SceneManager.update`です。
この中で更に`SceneManager.updateMain` →　`SceneManager.requestUpdate`を経て、pixiの`requestAnimationFrame`により次のフレームで再度`SceneManager.update`が呼び出されます。

この`SceneManager.updateMain`の中には`SceneManager.updateScene`があり、各Scene(Scene_Map/Scene_Battle等)のprototype.updateに繋がります。

#setWaitModeがしている事
前述の通り、Scene_Mapの場合、`Scene_Map.prototype.update`が呼び出され、その中にはイベントコマンドをコントロールするGame_Interpreterのupdateも、`Scene_Map.prototype.updateMainMultiply` →　`Scene_Map.prototype.updateMain` →　`Game_Map.prototype.update` →　`Game_Map.prototype.updateInterpreter`　を経由して呼び出されてます。

```javascript:rpg_object.js
Game_Interpreter.prototype.update = function() {
    while (this.isRunning()) {
        if (this.updateChild() || this.updateWait()) {
            break;
        }
        if (SceneManager.isSceneChanging()) {
            break;
        }
        if (!this.executeCommand()) {
            break;
        }
        if (this.checkFreeze()) {
            break;
        }
}
```
これを見ると分かる通り、`Game_Interpreter.prototype.updateWait`がtrueを返した場合、breakが発生し次のコマンドを実行するだろう`Game_Interpreter.prototype.executeCommand`は実行されません。
そして――

```javascript:rpg_object.js
Game_Interpreter.prototype.updateWaitMode = function() {
    var waiting = false;
    switch (this._waitMode) {
    case 'message':
        waiting = $gameMessage.isBusy();
        break;
    case 'transfer':
        waiting = $gamePlayer.isTransferring();
        break;
    case 'scroll':
        waiting = $gameMap.isScrolling();
        break;
    case 'route':
        waiting = this._character.isMoveRouteForcing();
        break;
    case 'animation':
        waiting = this._character.isAnimationPlaying();
        break;
    case 'balloon':
        waiting = this._character.isBalloonPlaying();
        break;
    case 'gather':
        waiting = $gamePlayer.areFollowersGathering();
        break;
    case 'action':
        waiting = BattleManager.isActionForced();
        break;
    case 'video':
        waiting = Graphics.isVideoPlaying();
        break;
    case 'image':
        waiting = !ImageManager.isReady();
        break;
    }
    if (!waiting) {
        this._waitMode = '';
    }
    return waiting;
};
```
こちらで分かる通り、_waitmodeに値がセットされていると、相応のパラメータをチェックし、まだ終わっていない場合は次のイベントコマンドに進まない仕組みになっております。


#結局何故スクリプトの中でsetWaitModeをセットしても次の行（スクリプト）が実行されてしまうのか
上記から分かる通り、waitmodeはあくまでも「一つのイベントコマンドから次のイベントコマンドに進むのを止める」効果を発揮してます。
同じスクリプトコマンドの中で改行しても、それは結局同じイベントコマンドの中身であり、それ故にwaitmodeは効果を発揮しません。
逆にスクリプトを別々のイベントコマンドに分けた場合、上記の通り、次のスクリプトイベントコマンドに進む事がupdateWaitmodeによって阻まれ、3行目相当の`AudioManager.playSe({name:'Attack1', volume:90, pitch:100, pan:0})`は実行されない…と言う事ですね。