事前のお知らせ

攻略本レベル5 プラグインの作り方 攻略本レベル5 プラグインの作り方:RPGツクールMZ

プラグインの作り方入門その7:プラグインコマンドの作り方(JavaScriptの配列) #RPGツクールMZ #RPGツクールMV

前回の記事では、プラグインパラメーターでスイッチを指定して、スイッチに応じてゲームオーバーの処理を変更するプラグインを作りました。
プラグインの作り方入門その6:スイッチに応じてゲームオーバーの処理を変更(プラグインパラメーター)

今回の目標(プラグインコマンドでウェブサイトを開く、アクターを変身(別アクターと交代)する)

今回はRPGツクールMV用のプラグインコマンドを作成します。
RPGツクールMZでMVのプラグインコマンドを実行する方法がありますし、次回はこのプラグインコマンドをMZに移植する方法を紹介します。
基本部分の作り方はMV・MZとも似ているので、RPGツクールMZの使い手にもお読みいただければと思います。

プラグインコマンドはコアを調べても作り方は分かりません。
コアを「pluginCommand」でGrepすると下記が出てきます。

Game_Interpreter.prototype.pluginCommand = function(command, args) {
    // to be overridden by plugins
};

「プラグインで上書きします」としかありません。

プラグインコマンドのテンプレート

この連載は筆者のモットー「真面目に勉強するのは辛いので、とりあえず動くものを作ってから考える(勉強する)」に従って、いきなり筆者のテンプレートを出します。

(() => {
    "use strict";

    const pluginName = 'ファイル名';

    const _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
    Game_Interpreter.prototype.pluginCommand = function (command, args) {
        _Game_Interpreter_pluginCommand.call(this, command, args);

        if (command === pluginName) {
            //処理
        }
    };

})();

このテンプレートは、公式プラグインのアイテム図鑑を参考にしています。
ちょっと変えてあるのは、プラグインコマンドのスペルを指定しないで、ファイル名を使用している所です。

これは、プラグインコマンドの競合を防ぐためです。
プラグインコマンドはプラグインパラメーターのように、関連付けて保存される仕様はありません。
このため、プラグイン作者が好きなスペルでプラグインコマンドを作成することが出来ます。
しかし、たまたま同じスペルを使ったコマンドを持つプラグインを複数入れていたら、容易に競合します。
これを防ぐためにプラグインパラメーターの考え方を取り入れたわけです。
(このアイディアを広めたのは神無月サスケ氏と予想されます)

この連載でこれまで、上書きしてきた関数は function(xxx) のxxxの中が無かったものでした。
ですので、フックするのに 「~.call(this) 」を加えていたのですが、今回は「function (command, args)」となっているため、このような書き方になります。

ちなみに、当該箇所はより短く書くことが出来ます。

// _Game_Interpreter_pluginCommand.call(this, command, args);
_Game_Interpreter_pluginCommand.apply(this, arguments); 


両方を紹介したのは、今後は他のプラグインの中を見て学んでいく事が増えると想定しているからです。
同じ処理でも、違う書き方(おそらく「.apply(this, arguments)」の方が多数派)をしているプラグインを見た時の手がかりにしてください。

callとapplyの違い

筆者は勘違いしていたのですが、callとapplyは働きが明確に異なります。
同じ書き方が可能なケースがありますが、callでなければ正常に動作しないケースがあります。
プラグインコマンドは配列を使用しているので、apply で動作しているのでしょうか?
command は配列でないので、エラーが出ていないだけなのかもしれません。
(ただ、この書き方をしているプラグインコマンドは多数見ます。)
値を返す関数をフックする場合、callを使用する必要があります。
どちらを使うべきか判断できない場合、callを使ったほうが安全と思われます。

call() メソッドは連続した引数のリストを受け取るのに対して、 apply() メソッドが引数の配列を 1 つだけ受け取るという点です。

developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

プラグインコマンドの仕様を確認

ツクール上で「スクリプト」を実行するのを簡略化するための仕組みと考えると理解しやすいです。

多くのプラグインにあるプラグインコマンドは、プラグイン内の動作を指定するコマンドとしてスクリプトを書くハードルを下げるために、そのプラグインの中の動作を呼び出すJavaScriptをプラグインコマンドの中に入れています。
この仕組がなければ、毎回スクリプトを書いてもらう事になっていたでしょう。

プラグインコマンドを動作させる

上記のテンプレートを「testPC.js」のファイル名で保存し、プラグイン管理で有効化します。
コード内の「ファイル名」の箇所も忘れずに書き換えてください。
まず、console.logを入れます。

(() => {
    "use strict";

    const pluginName = 'testPC';

    const _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
    Game_Interpreter.prototype.pluginCommand = function (command, args) {
        _Game_Interpreter_pluginCommand.call(this, command, args);

        if (command === pluginName) {
            console.log('command');
            console.log(command);
            console.log('args');
            console.log(args);
        }
    };

})();

プラグインコマンド「testPC a b1 c123」を実行して、ログを見ます。

下記のようなログが出ていますね。

testPC.js:11 command
testPC.js:12 testPC
testPC.js:13 args
testPC.js:14 (3) ["a", "b1", "c123"]

(3)の左にある三角をクリックすると、展開されます。

それでは、もう少し詳細を見ていきましょう。
下記のように、ログを追加します。

(() => {
    "use strict";

    const pluginName = 'testPC';

    const _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
    Game_Interpreter.prototype.pluginCommand = function (command, args) {
        _Game_Interpreter_pluginCommand.call(this, command, args);

        if (command === pluginName) {
            console.log('command');
            console.log(command);
            console.log('args');
            console.log(args);
            console.log('args[0]');
            console.log(args[0]);
            console.log('args[1]');
            console.log(args[1]);
            console.log('args[2]');
            console.log(args[2]);
            console.log('args.length');
            console.log(args.length);
        }
    };

})();

下記のようなログが出ていますね。

testPC.js:11 command
testPC.js:12 testPC
testPC.js:13 args
testPC.js:14 (3) ["a", "b1", "c123"]
testPC.js:15 args[0]
testPC.js:16 a
testPC.js:17 args[1]
testPC.js:18 b1
testPC.js:19 args[2]
testPC.js:20 c123
testPC.js:21 args.length
testPC.js:22 3

RPGツクールMVのプラグインコマンドでは、コマンド後に半角スペース区切りで項目を入力していく仕様になっています。
これをJavaScriptの変数の型の1つ「配列」に入れ["a", "b1", "c123"] のような形で保存されています。
この配列の1つずつを args[x] とすることで、文字列を変数に入れていくことが出来ます。
args[x]のxは0から連番で進みます。

「.length」は項目の数を引き出します。
他にも使い方があるので、JavaScriptのリファレンスで調べてみてください。
developer.mozilla.org/ja/docs/Learn/JavaScript/First_steps/Arrays

ウェブサイトを開くプラグインコマンドを作成

ウェブサイトを開くスクリプトは、「プラグインの作り方入門その3:コマンドを追加する」で調べてあります。
これをそのまま使用します。

答えは下記です。

(() => {
    "use strict";

    const pluginName = 'testPC';

    const _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
    Game_Interpreter.prototype.pluginCommand = function (command, args) {
        _Game_Interpreter_pluginCommand.call(this, command, args);

        if (command === pluginName) {
            const url = String(args[0]);
            window.open(url);
        }
    };

})();

上記にプラグインを修正し、プラグインコマンド

testPC https://tkool.jp/mv/

を実行してテストしてください。
URLを変えれば、違うサイトが開くはずです。
開かれるウィンドウの大きさなどを色々調整したい場合は、下記を参照しコードを変更してください。
developer.mozilla.org/ja/docs/Web/API/Window/open

アクターが変身(別アクターと交代)するプラグインコマンド

筆者はよく、Googleサジェストをチェックしています。
その中で、「主人公 交代」というのが気になっていました。
「ストーリーの途中で主人公が親から子供に移る」とかを想定しているのかな?と考えていたのですが、「呪術廻戦(アニメ)」を見ていて、「もしかして、主人公に取り付いている悪魔と交代してステータスもスキルもパワーアップする変身的な事も交代なんじゃない?」と考えて、作りました。
リクエストがあったわけでもないので、微妙ですがパーティの並び順を変えたりするのに応用できる知識なので、こちらで情報の整理をします。

まず、大まかなテストを書いて、ログを見ることでどのように実装していくのかの情報を整理します。

(() => {
    "use strict";

    const pluginName = 'testPC';

    const _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
    Game_Interpreter.prototype.pluginCommand = function (command, args) {
        _Game_Interpreter_pluginCommand.call(this, command, args);

        if (command == pluginName) {
            const before = Number(args[0]);
            const after = Number(args[1]);

            console.log($gameParty);
            console.log($gameParty._actors);
            console.log($gameParty._actors.indexOf(before));

            $gameParty._actors.splice($gameParty._actors.indexOf(before), 1, after);
            $gamePlayer.refresh();
            $gameMap.requestRefresh();
        }
    };

})();

上記をプラグイン(testPC.js)にし、プラグインコマンド「testPC 1 5」を実行します。

下記のようなログが出ています。

testPC.js:25 Game_Party {_inBattle: false, _gold: 0, _steps: 0, _lastItem: Game_Item, _menuActorId: 0, …}_actors:
(4) [5, 2, 3, 4]_armors: {}_gold: 0_inBattle: false_items: {}_lastItem: Game_Item {_dataClass: "", _itemId: 0}_menuActorId: 0_steps: 0_targetActorId: 0_weapons: {}__proto__: Game_Unit
testPC.js:26 (4) [1, 2, 3, 4]0: 51: 22: 33: 4length: 4__proto__: Array(0)
testPC.js:27 0

今回のプラグインコマンドは「アクターID1のパーティメンバーをアクターID5のアクターと入れ替えるという内容です。
並び順をそのままにしたかったので、少し手が込んでいます。

まず、ログの最初「console.log($gameParty); 」で、パーティのデータを引き出しています。
この左側にある三角をクリックしデータを見てみましょう。

_actors:(4) [5, 2, 3, 4] に注目してください。
これはアクターが4人いて、並び順にアクターIDが入っています。
これは変身後のデータが表示されているのか、先頭のID1がID5に入れ替わっています。
この配列だけを引き出すための方法が、次のログ「console.log($gameParty._actors); 」に入っています。
このように、元の全体のデータが引き出せれば、その部分的なデータは「~.項目名」とドットを入れてつなぐことで、部分的に引き出すことが可能なのが分かります。
この大元のデータの引き出し方は、トリアコンタン氏作のスプレッドシート等が参考になるでしょう。

indexOf:JavaScript

最後の「console.log($gameParty._actors.indexOf(before));」はJavaScriptの知識が必要です。
これまでの情報で書いたとおり、配列は[a,b,c]のように括弧内に要素が入っています。
「indexOf(xxx)」はJavaScriptで配列の中に同じ内容が何番目に入っているのかを返します。
順番のカウントは0から始まります。
developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
今回は、これを使って指定のアクターIDがパーティの何番目に入っているのかを調べています。

splice:JavaScript

次の「splice」で配列を置換しています。
developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/splice

最後の2行はツクールのゲーム内のリフレッシュ処理です。

$gamePlayer.refresh();
$gameMap.requestRefresh();

これを行わないと、アクターがマップ画面で入れ替わっても表示されているキャラクターが入れ替え前のままになってしまうため実行します。

まとめ

プラグインコマンドでJavaScriptが実行できるのが、ご理解いただけたかと思います。
プラグインコマンド単体のプラグインもありますが、多くはプラグインで追加された機能に対して、何らかの指示(機能のON/OFF等)を行うために設定するケースが多いです。
この場合、そのプラグイン内をスクリプトで呼び出しているというわけです。

完成品は下記です。
fungamemake.com/archives/12051

次のステップ

RPGツクールMZ用にプラグインコマンドを移植します。
仕様を把握し、JSONデータを扱う初歩に触れます。

プラグインの作り方入門その8:MZプラグインコマンドの作り方(JSONデータ)

スポンサードリンク

スポンサードリンク

-攻略本レベル5 プラグインの作り方, 攻略本レベル5 プラグインの作り方:RPGツクールMZ
-,

Copyright© RPGツクールMZ・MV初心者的備忘録 - FGMG (Fun Game Make Group) , 2024 All Rights Reserved.