コモンイベント内で装備画面を呼び出すと以降の処理が実行されず困っています。

アバター
サブちゃんB
記事: 27
登録日時: 2018年3月06日(火) 01:09

コモンイベント内で装備画面を呼び出すと以降の処理が実行されず困っています。

投稿記事by サブちゃんB » 2023年1月03日(火) 23:41

新年あけましておめでとうございます。
本年もご指導宜しくお願い致します。

トリアコンタン様のカスタムメニュープラグインからパーティーにいるアクター一覧ウインドウを作成し、
アクター情報を変数44に代入した状態で呼び出されるコモンイベント内で、

コード: 全て選択

$gameParty.setMenuActor($gameVariables.value(44));
SceneManager.push(Scene_Equip);

というスクリプトから装備画面を呼び出し、
装備画面を閉じた後に、
当該アクターが装備している武器と防具に応じてステートを付与することを目指しています。

スクリーンショット 2023-01-03 23.27.00_trim.jpg


しかし、装備画面を閉じるとそれ以降の処理が実行されないまま
アクター一覧ウインドウへ戻ってしまいます。
スクリプトを閉じずにその下へ書いた処理は、
なぜか装備画面が表示される前に実行されてしまいますので、
装備変更後の結果に応じたステート付与という目的が達成できません。

装備画面を開く前にスイッチを入れて、
アクター一覧ウインドウへ戻ったときにそのスイッチが入っているときのみ実行されるコモンイベントを実行させるという悪あがきも試してみましたが、
そのコモンイベントが実行されるのはアクター一覧ウインドウを閉じたときなので失敗です。

スクリプト部分を別のコモンイベントへ分けて実行しても結果は同じです。

万事休す、困っています。
どうかお知恵をお貸し頂けないでしょうか。
宜しくお願い致します。

名無し蛙
記事: 310
登録日時: 2015年11月23日(月) 02:46

Re: コモンイベント内で装備画面を呼び出すと以降の処理が実行されず困っています。

投稿記事by 名無し蛙 » 2023年1月05日(木) 23:36

https://github.com/triacontane/RPGMakerMV/blob/master/SceneCustomMenu.js

入れてるプラグインはこれですか?
ブラウザ上でコードを斜め読みした感想ですけど仕様としか言いようがないのでは

コード: 全て選択

    class Scene_CustomMenu extends Scene_MenuBase {
        create() {
            super.create();
            this.swapGameScreen();
            this._interpreter = new Game_Interpreter();
            this._customData  = SceneManager.findSceneData(getClassName(this));
            this.createAllObjects();
        }

インタプリタのインスタンスを直接Sceneに持たせてますよこれ。
例えば普通のマップイベントならグローバルオブジェクト($gameMap)にインタプリタを持たせて
Sceneで動かしています。
その場合はシーン遷移したとしてもインタプリタの挙動に直接影響を与える事はありません。
しかしSceneに直接持たせるという事はシーン遷移、つまりシーンの解放&生成時に一緒に解放されるので
当然、イベントリストの進行状況等も全て消去されてしまいます。

Scene外にインタプリタのインスタンスを確保して
従来のインタプリタ生成部分をただの設定に置き換えれば動きそうな感じはしますね。
ただし知識が不十分な状態で第三者のプラグインを改造するのはあまりお勧めできませんが。
アップデートを適用する度に整合性チェックするのも面倒ですし。
何をするにしても自作プラグインを使う必要があるなら
Scene_Equip.prototype.createやterminateを改造すれば良くないか、って気もしますね。
アバター
サブちゃんB
記事: 27
登録日時: 2018年3月06日(火) 01:09

Re: コモンイベント内で装備画面を呼び出すと以降の処理が実行されず困っています。

投稿記事by サブちゃんB » 2023年1月06日(金) 14:46

名無し蛙様、いつもご指導本当にありがとうございます!
コモンイベント内で起きている困り事なので、呼び出したプラグインが起因しているとは気がつきませんでした。
まだまださっぱり修行が足りませんね。
プラグインの仕様ということをご教示頂いたので、別の手段を模索し、お陰様でうまくいきそうな手が見いだせました。

コード: 全て選択

   Game_Temp.prototype.EqCloseStates = function(){
      const EQProsValNum = 87;
      if($gameSwitches.value(EQProsValNum)){
         console.log("ステート処理!");
         $gameSwitches.setValue(EQProsValNum,false)

      }
   }

   SceneManager.pop = function() {
      if (this._stack.length > 0) {
         // console.log("装備画面を閉じる直前の処理をここへ記述");
         $gameTemp.EqCloseStates();
         this.goto(this._stack.pop());
      } else {
         this.exit();
      }
   };


装備画面を呼び出す前にステート処理を1回だけ実行するためのスイッチを入れておいてから装備画面を開き、
処理が終わったらスイッチを切る関数を挿入しています。

この処理をプラグイン化して実行したところ、希望通りのタイミングで動いてくれるようです。
この手で出来るかどうかやってみて、詰まったらまた質問させて頂きます。
いつもお助け頂き、本当にありがとうございます。
本年も引き続きご指導のほど、宜しくお願い致します。
最後に編集したユーザー サブちゃんB on 2023年1月08日(日) 17:45 [ 編集 1 回目 ]
名無し蛙
記事: 310
登録日時: 2015年11月23日(月) 02:46

Re: コモンイベント内で装備画面を呼び出すと以降の処理が実行されず困っています。

投稿記事by 名無し蛙 » 2023年1月07日(土) 04:47

自分の理解が及ぶ範囲で管理するのが一番良いので実装手段に関してはあまり口を挟みませんが、
SceneManager.popは少なくともSceneCustomMenu内でも再定義しているので
プラグインマネージャの順番には注意した方が良いですよ。

コード: 全て選択

// SceneCustomMenu内
    const _SceneManager_pop = SceneManager.pop;
    SceneManager.pop        = function() {
        _SceneManager_pop.apply(this, arguments);
        this._sceneIndex = 0;
    };

一応、インタプリタに関する補足というか基礎説明もしておきます。
インタプリタとはイベントリストを読み解き、実行する役割を持つオブジェクトです。
イベントリストが楽譜ならインタプリタが演奏者みたいな関係ですね。
イベント単体で動作する事は有り得ず、
またイベントが動作している間は必ずイベントリストとインタプリタは対の関係になっています。
その為、イベントリストの動き方に違和感がある場合はインタプリタをチェックするべきです。

コアスクリプト内にインタプリタは5種類存在し、それぞれ挙動が異なります。
Game_Mapに存在するものは主にマップイベント用。
Game_Troopに存在するものはバトルイベント用。
Game_Eventに存在するものは並列処理のマップイベント専用。
Game_CommonEventに存在するものは並列処理のコモンイベント専用。
Game_Interpreterに存在するものはイベント内で入れ子構造で呼び出すコモンイベント用。

基本的に目的に応じて既存のインタプリタを使い分けるのですが
見ての通りメニュー中に動作するインタプリタは一つも存在しません。
その為Scene_CustomMenu.prototype._interpreterで新しいインタプリタを用意し、
それに指定のコモンイベントリストを実行させる設計になっています。
ただし、ところどころ簡略化されており
大きなものだとシーンに直接インタプリタの実体を持たせている、という点があります。

シーン遷移処理(SceneManager.push)とは知っての通り現在のシーンを破棄し
新しいシーンを生成し設定する一連の処理の事です。
その為シーンが内包するインタプリタも同時に破棄されます。
それが今回の題意(装備画面を呼び出すと以降の処理が実行されず)に繋がっている現象だと思いますね。
アバター
サブちゃんB
記事: 27
登録日時: 2018年3月06日(火) 01:09

Re: コモンイベント内で装備画面を呼び出すと以降の処理が実行されず困っています。

投稿記事by サブちゃんB » 2023年1月08日(日) 12:48

名無し蛙様、ご教示感謝致します!

もしご教示頂いたことを知らないままでいたら、
今後これが原因でトラブルが発生した場合に原因が分からず混乱していたところでした。
このプラグインで再定義している関数を書き換えているので、
不具合が発生する可能性が十二分にありますね。

Scene_Equip.prototype.create、またはSceneManager.terminateへ関数を追加すると、
装備画面を閉じたタイミングではなくて
アクターリストを閉じたタイミングでの実行になってしまうので、
SceneManager.popの書き換え以外の手段が見いだせません。
場合によっては、プラグインのSceneManager.pop内で
希望の処理を実行させるよう書き換える等の手段も検討致します。

アクターやアイテムの処理に比べてScene関係の処理はずいぶん複雑なので理解を諦め、
UI関係はプラグインに頼り切りです。
そのため、詳しい方から丁寧にご解説頂けるのは本当に助かります。
名無し蛙
記事: 310
登録日時: 2015年11月23日(月) 02:46

Re: コモンイベント内で装備画面を呼び出すと以降の処理が実行されず困っています。

投稿記事by 名無し蛙 » 2023年1月09日(月) 05:24

サブちゃんB さんが書きました:Scene_Equip.prototype.create、またはSceneManager.terminateへ関数を追加すると、
装備画面を閉じたタイミングではなくて
アクターリストを閉じたタイミングでの実行になってしまうので、
SceneManager.popの書き換え以外の手段が見いだせません。

なるほど。妙な誤解をすると思ったらオブジェクト指向の「継承」の知識が欠けてるんですね。
簡単な例を書くならこんな感じです。

コード: 全て選択

class Animal {
    name() {return "動物";}
}
class Cat extends Animal {}

// AnimalのメソッドはCatも呼び出せる(継承)
console.log(`吾輩は${new Animal().name()}である`); // 吾輩は動物である
console.log(`吾輩は${new Cat().name()}である`); // 吾輩は動物である

// Animalに影響を与えずCatのメソッドだけ改造可能(多態性)
Cat.prototype.name = () => "猫";
console.log(`吾輩は${new Animal().name()}である`); // 吾輩は動物である
console.log(`吾輩は${new Cat().name()}である`); // 吾輩は猫である

自分が書いたのはSceneManager.terminateではなくScene_Equip.prototype.terminateの事です。
コアスクリプト内には記述はありませんが
Scene_Base(を継承したScene_MenuBase)を継承している為、確かに存在します。
createは生成した直後に、terminateは破棄する直前に呼ばれるのでここは改造の基本です。

コード: 全て選択

/*
// 記述が省略されているだけでこんなメソッドが存在すると考えてください
Scene_Equip.prototype.terminate  = function() {
    Scene_MenuBase.prototype.terminate.apply(this, arguments);
};
*/

// シーンから脱出する時に処理を加えたい場合はterminateに処理を追加
const _Scene_Equip_terminate = Scene_Equip.prototype.terminate;
Scene_Equip.prototype.terminate  = function() {
    _Scene_Equip_terminate.apply(this, arguments);
    // ここに記述
};


余談ですけど1/13までSteamで90%OFFのVXAceの購入を薦めます。
初心者がMZのコアスクリプトを解読するのはかなり厳しいですよ。
プロトタイプベースのOOPという時点でかなりクセがあり、更にコメントもまともに振られていない。
ツクールの仕様はVXAceでほとんど固まってる為システム設計もMZと大差がなく
クラスベースのOOPなので比較的解読し易く、全てのメソッドに日本語でコメントが振ってあります。
おまけに改造のチュートリアルもヘルプに記載されています。
学習用資料として割り切っても十分価値があると思いますね。
アバター
サブちゃんB
記事: 27
登録日時: 2018年3月06日(火) 01:09

Re: コモンイベント内で装備画面を呼び出すと以降の処理が実行されず困っています。

投稿記事by サブちゃんB » 2023年1月10日(火) 15:15

名無し蛙様、ご教示ありがとうございました。
Scene_Equip.prototype.terminateが実は存在するということを全然知りませんでした!
省略されている、とは、こういうことだったのですね。
ご教示頂いた通りにプラグイン化したところ、希望通りに動いてくれました!

オブジェクト指向については、もう何年も前に概念だけ流し読みした程度で実践的なことは演習すらしていませんでした。
しっかり勉強していないことでこれほどまでハンデを背負うことになるとは。

VXAce、実はMVをバンドルで買ったので持っておりますが、結局使わなかったので塩漬けになっていました。
スクリプトエディタを開いてみて驚愕です。
マニュアルがないに等しいMV、あっても誤植訂正すらしないMZからは想像が付かないほど丁寧ですね。
command_番号 とかサッパリ意味が分かりませんでしたが、ここから引けばいいんですね。
Scene関係も解説があるので、独自にグラフィカルな機能を実装するときは参考にしたいと思います。

大変ありがとうございました。

“MZ:質問” へ戻る