ニル 2020/12/10 00:00

スクリプトの知識がなくても、自分と一緒に簡単なプラグインを作ってみましょう!

ツクールフォーラムアドベントカレンダー Advent Calendar 2020

https://adventar.org/calendars/5074

https://forum.tkool.jp/index.php?threads/【募集中】アドベントカレンダー2020.4530/#post-26453

まえがきの後は、特定スロットの武具の名前を、職業欄に表示するスクリプトを作成していきます。


まえがき(読み飛ばして頂いて構いません)

さて、今年は書く方が不足しているということで、久々にci-enで筆を取ってみたわけであります。

自分は、RPGツクールMV Trinityのps4版を発売直後に定価で購入したのが、初のツクールであり、
紆余曲折あり2019年の春前にMVへと移行してきました。

その時に感動したのが、プラグインという素晴らしいモノがあること。
そして、プラグインを利用するにも、スクリプトへの理解という壁が、何処までもついてまわるという事を実感しました。

競合の問題。欲しいゲーム内情報の取得法。何度も掲示板やSNSで諸先輩方に助けてもらって今があります。

そんな自分の現在はというと、バリバリスクリプトを書けるようになった!
なんてことはなく、初心者の粋を出て初級者にはなっている……と信じたい。
といった程度です。

自分で必要な分のゲーム内の情報を取得したり、
自分用のプラグインを(複雑なものではないです)書いたり、
他の方のプラグインを自分のゲーム用に多少調整出来る程度は、
なんとか出来るようになりました。

画面は現在作っているゲームのステータス画面です。
一応完全自作。頑張って作りました。


教える立場にいるのかといえば、
そんなレベルには達していないと自覚しておりますが、
右も左も分からなかった頃が直近であるからこそ、
特に何が分からなかったかをまだ覚えております。

もしここで自分がおかしな事を書けばきっと諸先輩方が指摘をしてくれるでしょうし、
もうそうなった場合は自分も一緒に学ばせてもらおう。
そして、お世話になった界隈に少しでも還元をと思い、書いていきます。

ぶっちゃけ記事の中で多くの部分に多分とついてしまう程度なのですが、かといって文章中に(多分)(多分)と
書きまくるのはあまりにウザいので割愛しますが、
実際問題、その程度の知識量であるということをご了承くださいませ。

スクリプトに関して、まず何に躓いたのか。

自分が当時、最も始めに疑問に思い、理解に時間がかかった事を書いていきます。

プラグインとはどうやって、いつロードされているのか。

プラグインっていつどうやってロードされてるんだ?
コモンイベントみたいに、呼ぶための命令をすれば良いのか?
もしそうなら、その命令とは?

プラグインコマンドで呼ぶものやメモ欄に記述するもの。
呼ばなくても動くもの。それらが混在することで、
特に、呼ばずに動くものは何故動くのかが当初理解できませんでした。

プラグインへの認識が、お借りして入れると(何故か)動く。
そういう風に作ったのであろうという事は理解出来ても、
それがどういう風に作ったらそうなるのかわからない。という感じでした。


これに関しては、

ゲーム中は常にスクリプトは常に絶え間なく呼び出されているものであり、
何かしら起動しているからです。

イメージ的にはイベントコマンドの並列処理がずーっと走っている感じでしょうか。


そして、プラグインとはコアスクリプトを上書き・或いは拡張するものであり、
コアスクリプトの処理に追加したり、
本来の処理と別のルートを辿らせる事で、
コアスクリプトが起動していく一連の動作の中で、呼び出されていきます。


つまり、然るべき場所(処理の近しい場所)にやりたい処理を追加する事が出来れば、
それだけで簡単なプラグインであれば書くことが出来ます。

例えばクリティカル威力を変更したり、アイテムの取得時にはそのIDをゲーム内変数に代入したり、TP再生を固定値ではなく割合にしたり。リザルト画面を消したり。
などなど。

その為にはまず、然るべき場所とはコアスクリプトの何処であるのかを見つける方法を身に着けなくてはいけません。


今回は例として、ステータス画面に表示されている職業名の場所に、
装備中の防具の名を参照するようにする。……ということをしてみます。

例えばその防具を称号として扱えば、付けている称号がステータス画面に表示される。
ということになりますよね? そんな感じです。

何処を修正したいのか探そう。

コアスクリプトは

rmmz_core
rmmz_managers
rmmz_objects
rmmz_scenes
rmmz_sprites
rmmz_windows

から構成されています。詳しい説明はもう他の方でしてる方も多いですし、
絶対そっち見たほうが良いので割愛します。

何処に入ってるかわからない?
そんなもん何となく分かるようになってくるまで、
全部開いてCTRL+Fで検索掛ければ良いんです。

料理だってそうでしょう?
レシピ見なくても作れたり味見しなくてもマトモな味が作れるようになるには、
それ相応に料理に触れていかねばならないし、
触れてるうちになんとなく分かってくるんです。
右も左もわからないうちは手間がかかる。それはしょうがない事なんですよ。


因みに自分はプラグイン触るときは未だに全部コアスクリプト開きっぱなしです。



今回はステータス画面で、職業の表示です。

まず、statusでコアスクリプト内を検索してみます。487件ヒットしました。
これじゃダメですね。一個一個見ていっても良いですが……。

では、次にclassで検索します。これは176件ヒットしました。だいぶマシですね。
慣れてくればステータス画面の表示だから、
このコアスクリプトの中かな……と絞ることが出来て、
この状態でも簡単に然るべき場所にたどり着けるのですが、
当時は自分もそれが出来なかったので、考え方を変えてみます。

ステータス画面。表記は他にもあります。
最終的に変えたいのは職業の表記ですが、近くには二つ名などもありますね。
処理が近しいものは、大体同じコアスクリプトの中にありますので、
次は二つ名で探してみましょう。

でも職業はクラス。ステータスはステータスでわかりましたが、二つ名とはどう探せばいいのか?

ここでは2つの方法を提示します。

一つ、トリアコンタンさんのMZの非公式スクリプトリファレンスをお借りします。
二つ名と検索することで、

$dataActors[id].nickname

と記述してあります。
二つ名に関するデータがnicknameであると気づければok。


もう一つは、テストプレイ中のコンソールログを使います。
コンソールログは、エラーが出てくる画面。

……だけではなく、下の入力欄に適正な記述を行うと、
ゲーム内のデータを見ることが出来ます。

コンソールログの使い方

テストプレイ中にF12を押すと出てきます。

こんなのですね。


とりあえずこれを開いて。

$gameActors.actor(アクターID).setNickname("変更する二つ名")

次に、こういう記述がどういう意味なのか紐解いておきましょう。
これも正直、自分は理解までに時間をかけました。

. ←は、そのデータ群の中の……或は命令という感じです。
何が情報群で何が命令なのか、分かってくるまで非常にわかりにくいです。
例えばですけど

$gameActors.actor(アクターID).setNickname("変更する二つ名")
↑これはこんなイメージ
植物.野菜(大根).品種名を変えなさい(”おろし”)

一行の中に、何処のデータで何をしろ。
というのが収まっているので理解がしにくかったんですよね。
ここから命令部分を切り落としてしまえば、そのデータを参照出来るものもあります。

カッコの中の数字は何番のIDの情報を見るか。という指定なので、

$gameActors.actor(1)

この記述で見てみましょう。
▶を押してみるとずらーっとデータの羅列が出てきます。

見ていくと、見覚えのある名前が出てくると思います。
自分の場合だと、アクターの名前である ブレン や、二つ名のEクラス冒険者ですね。

このデータを見れることはとても重要で、
ゲーム内情報を得るだけでなく、変更する際にも大きな足掛かりになります。

今回であればアクターの情報はもう見えています。
そして、中の値を書き換えてしまえば、それを変更出来るんですから。

例えばこのコンソールログに

$gameActors.actor(1)._paramPlus[3] =999
と打ち込めば、アクター1番の防御力に999に入れなさい。となります。


HPにも10万入れていたので、職業由来の値と合わせて
HP:10450
防御:1015
のチート使ったみたいなアルドくんが数十秒で完成です。
中の値を見れるということは、簡単に書き換えられるということ。
よって、中の値を発見する事こそ、大事であることをよく覚えておいてください。

ともあれ、$gameActors.actor()の中身を覗いてみたことで、
二つ名は _nickname に入っていることがわかりました。
とりあえず_は抜いて、nicknameでコアスクリプト内を検索をしてみましょう。

そうすると、14件しかヒットしません!
これなら絞り込めそうですね。

色々見ていくと、いかにも怪しげな

という記述が見つかります。名前、クラス、ニックネーム。
それと、window_Statusという名前。

そうです、ここはもう然るべき場所の一歩手前です。

this.はとても難しいのですが、
今回の場合は、現在の参照値と同じ名を持つフロアの。というような感じ。

ここで、本来変更したいのはクラスであることを考え、
drawActorClassでもう一度検索します。
すると、3件だけヒットしました。

Window_StatusBase.prototype.drawActorClass = function(actor, x, y, width) {

width = width || 168;
this.resetTextColor();
this.drawText(actor.currentClass().name, x, y, width);

};

そのうちの1件がこれ。
drawTextというのは、非常によく出てきます。
文章を表示している命令です。
これは、actor.currentClass().nameをx座標はxにy座標はyに幅widthで記述せよ。と言った感じ。


ここが目的地です。お疲れさまでした!
俺ももうかれこれ、3時間くらい記事書いてます。疲れてきました。

これをプラグインにする。以下をコピーして貼り付け

/*============================================================================
syokugyouhyouziwohenkousuru.js
---------------------------------------------------------------------------
(C)2020 あなた
This software is released under the MIT License.
http://opensource.org/licenses/mit-license.php
---------------------------------------------------------------------------
Version
1.0.0 2020/12/09 初版


[Blog] :
[Twitter]:
============================================================================/
/
:
@target MZ
@plugindesc 職業表示を変更する
@author あなた

*/

(() => {
//ここから必要な記述を行う
Window_StatusBase.prototype.drawActorClass = function(actor, x, y, width) {

width = width || 168;
this.resetTextColor();
this.drawText(actor.currentClass().name, x, y, width);

};
//ここまで必要な記述を行う
})();

↑ここまで

これに、適当な名前をつけて拡張子を.jsで保存します。
メモ帳の場合はUTF-8じゃないとダメだったかと思います。

自分も暫くメモ帳をつかっていましたが、エディタをオススメされまして。
実際、色分けされているとコードの意味がわかりやすいので、
そういった機能があるやつを使うほうが良いかと思います。

因みに自分はatomですが、他人にコードを見せる(相談する)
場合に自動整形するなりして、せめて見やすくするのは最低限度のマナーである。
……みたいな事を目にして、なるほどじゃあ自動整形機能があるのにしようと、
最初に目についたのがこれであったというだけで、その他に特に理由はありません。

諸先輩方がきっとおすすめを教えてくれることでしょう。



で、これを普段使っているプラグインと同様の場所に入れて、ゲーム内からいつもどおりに入れれば、あなたのプラグインが完成しました!

とはいえ、このプラグインは、
コアスクリプトを全く同じ記述でを上書きするだけのものです。
現実的には、競合を引き起こす可能性があるだけのプラグインということになります。


ここで競合についても少しお話します。
今回、プラグイン化にあたって、これ↓の中身を改変します。

Window_StatusBase.prototype.drawActorClass

プラグインはコアスクリプトに対して、上に置いてあるものから上書き保存をして、最終的に出来上がったものを、あなたのゲームで起動します(多分)

プラグインの競合というのは、この過程で、
同じものを複数の場所で上書きした時には必ず起こります。

クリティカル威力は本来の威力の100倍にせよ。

と、コアスクリプトに上書きをした後に、

クリティカル威力は本来の威力の1000倍にせよ。

という上書きをすれば、片方は機能しなくなりますよね。そういうことです。
これが、クリティカル計算の値を100倍する挙動を、本来の挙動にプラスせよ。
みたいな書き方になると、挙動の追加が積み重なり100000倍になったりしますがー。


とりあえず概要の話なのでここでは置いておきます。


さて、次にプラグイン化した方の記述を変えていきます。
これが職業を記述している項目です。

this.drawText(actor.currentClass().name, x, y, width);

では、これをどうしたいのかを考えます。

称号の装備がない時は、職業本来の名前を表示し、
称号があるときはそれを優先表示することにしました。

はい、どーん。 ……流石に疲れてきたので。

改変後

Window_StatusBase.prototype.drawActorClass = function(actor, x, y, width) {

width = width || 168;
this.resetTextColor();
if ($dataArmors[actor._equips[4]._itemId] == null) {
  this.drawText(actor.currentClass().name, x, y, width);
  return;
}
if (actor._equips[4]._itemId == 0) {
  this.drawText(actor.currentClass().name, x, y, width);
}else{
  this.drawText($dataArmors[actor._equips[4]._itemId].name, x, y, width);
}

};

ここまで

actor._equips[4] というのは、アクターの装備で5箇所目を意味します。
プラグインとかで変化していなければ、装備画面で上から5番目の位置です。

そこを参照します。
actor._equips[4].itemId
となると、装備画面で上から5箇所目の装備エリアのアイテムのIDとなります。
今回は5箇所目に防具を装備しているので、防具のIDを参照します。
プラグインで弄らない限りは0番が武器でそれ以外は防具ですが。

$dataArmors[].name

というのは、防具データ[]番の名前を参照する。ということです。
つまり、この2つを合わせて

$dataArmors[actor._equips[4]._itemId].name

こうなると、五箇所目に装備中の”何か”のIDと同じIDを持つ防具の名前を参照せよ。です。

this.drawText(,x,y,width)は少し難しいのですが、

そもそも、大本のこれ↓が呼び出された際、
Window_StatusBase.prototype.drawActorClass

actorとxとyとwidthの数値を受け取ってきています。


Window_Status.prototype.drawBlock1 = function() {

const y = this.block1Y();
this.drawActorName(this._actor, 6, y, 168);
this.drawActorClass(this._actor, 192, y, 168);
this.drawActorNickname(this._actor, 432, y, 270);

};

この中にある、

this.drawActorClass(this._actor, 192, y, 168);

呼び出し元のこの記述ですね。
this._actorはこの場面では、ステータス画面で選択中のアクターを指します。
xは192と指定され、yはblock1Yというところから取ってきたモノを、更に渡しています。

因みにblock1Yを追いかけると、

Window_Status.prototype.block1Y = function() {

return 0;

};
となっています。returnというのは、これが呼び出された時には右の値を返せと言うことなので、0を返します。

つまり、block1Yは0です。block1YをYという名前に変えて、
値はそのままに現在プラグインで作成中の、
Window_StatusBase.prototype.drawActorClass に持ってきたということですね。


Window_StatusBase.prototype.drawActorClassの中で
先程説明した actor._equips[4] ですが、アクターの番号の指定がないのにも関わらず、それがID何番のアクターであるかの情報を持っていたのは、直前に受け渡されている

this.actor が何番のアクターであるかの情報をもっていて、それをactorという名前で受け取ってきているからですね。


……俺のこんな説明でわかるでしょうか?
同じ actor に見えるのにある場所ではカッコが付いて番号指定があったり、
ある場所では直接参照しているように見えたり、理解がし辛いと思いますが、

その文字列に拘って見るのではなく、それに入っている情報が
何処からきた情報であるかを追っていかないとダメ。ということですね。

ここでお役立ち情報。

これなんの情報持ってんだよって思ったときには

console.log();

をスクリプトの間に記述してみましょう。


Window_StatusBase.prototype.drawActorClass = function(actor, x, y, width) {

width = width || 168;
this.resetTextColor();
this.drawText(actor.currentClass().name, x, y, width);

};


例えば今回の大本。改変前のこれで言えば、actorとかthisなんかはわかりにくいですよね。こんなときは


Window_StatusBase.prototype.drawActorClass = function(actor, x, y, width) {

width = width || 168;
console.log(this);
console.log(actor);
this.resetTextColor();
this.drawText(actor.currentClass().name, x, y, width);

};

のように、記述することで、thisとactorが持っている情報をコンソールログに出力せよ。という命令になります。この状態でテストプレイを開始し、F12でコンソールログを開けば、該当した場所が呼び出された時に、このスクリプト内の何行目の出力結果がこれ!

今回であればステータス画面を開いたりすると、コンソールログが出力されると思います。このように console.log(); は値の特定に極めて役立ちます。

困ったら console.log(); です。
勿論、カッコ内に何を出力させるかの指定を忘れずに。


こんなものでしょうか。
……プラグインを書いたりしていたら7時間もかかってしまいました。

今回書いたのはステータス画面用に。ではあるのですが、

Window_StatusBase.prototype.drawActorClass

は機能が最小限で、とても汎用的なモノなので、
ステータス表示の一環として、スキル欄での職業表示でも呼び出されているようです。
なので、特に何もせずともステータス画面と同様に防具名になったりします。

その他のプラグイン独自のシーンに呼び出されているケースもありますし、
その場合でも、

Window_StatusBase.prototype.drawActorClass
を呼び出しているのなら同様に特に何もせずとも変更されます。


さ、これで自分の記事も終了です。


誰かのお役に立てば幸いです。
そして、間違いの多い記事だったら大変申し訳ありません。


最後に、完成後にもう少し使いやすくした状態のプラグインです。
職業名か二つ名の表示欄に武具の名前を表示させるプラグインは
スクリプト内に注釈を書きまくりました。何かの役に立てば幸いです。


そして、以前Twitterでひっそり公開したプラグインの再掲示もしておきます。

職業名か二つ名の表示欄に武具の名前を表示させるプラグイン

https://drive.google.com/file/d/11fgMnFm9sEArMJyab8Q8A9gz_0QPHbJ7/view?usp=sharing

TPBにおいてスキル後にゲージが溜まっているスキルや装備がつくれるプラグイン

https://drive.google.com/file/d/1BOsEBFdsESVJSZzfIkEH3EKfhLvQb5DZ/view?usp=sharing

TPBにおいて、キャストタイムを軽減するスキルや装備が作れるプラグイン

https://drive.google.com/file/d/18nIe1hp1vEi0dwexfFu_S0Ag52EFIdcL/view?usp=sharing

記事のタグから探す

月別アーカイブ

限定特典から探す

記事を検索