見出し画像

ゲーム起動からデータjsonが読まれるまでの処理の流れとかいま書いてるプラグインとか

プラグインを書いてたらいろいろ見る羽目に

前回はかいしんのいちげきのダメージをMZデフォルトからちょっとカスタマイズするプラグインを書いていたんですが、今回はDQ2準拠でLVごとに各アクターの最大HP/MPとかちからとかみのまもりとかそういうパラメータを、エディタ上の成長曲線の設定を無視して直接固定値で指定するプラグインというのを書いていました。さっきようやく例外でコケずにぱっと見大丈夫そうなところまできたんですが、結果的になかなか骨がある課題になりました。

必要経験値はいちいち計算している

で、レベルごとの必要経験値は、ゲームエディタで設定する基本値/補正値/増加度A/増加度Bを使って Game_Actor クラスの中で毎回いちいち計算してるようでした(そんなに負荷のかかる計算ではなさそうだとはいえ)。

Game_Actor.prototype.expForLevel = function(level) {
   const c = this.currentClass();
   const basis = c.expParams[0];
   const extra = c.expParams[1];
   const acc_a = c.expParams[2];
   const acc_b = c.expParams[3];
   return Math.round(
       (basis * Math.pow(level - 1, 0.9 + acc_a / 250) * level * (level + 1)) /
           (6 + Math.pow(level, 2) / 50 / acc_b) +
           (level - 1) * extra
   );
};

これなら、どこかに返す内容をかかえたリストなりなんなりをconstでかかえておいて、職業IDとレベルを引数にしたら結果をぽんと返してくれるようにここの定義を上書きしてしまえばよさそうだな、ということで実際そうしたらうまくいきました。今回はプラグインの中に直に書きましたが、なんなら data/ExpForLevel.json とかつくっておいてもよかったかもしれないですね。

const expForLevel = {
    classId: [
        0, Lv1に必要な経験値, Lv2, Lv3, ...
    ], 
    // ......
};

↑こんなんをどこかに書いといて、

Game_Actor.prototype.expForLevel = function(level) {
   const c = this.currentClass();
   const classId = c.id;
   return expForLevel[classId][level];
};

↑こんな感じでとりあえず。

MZはデータをjsonでかかえている

MVですでにそうだったかもしれないんですが、なんかよくわからんバイナリでかかえていた(*1)VXからの移行なのでだいぶ開発者フレンドリーになったもんだなと、ちょっとした感慨がありました。

レベルごとのパラメータのほうは、どうもゲームエディタの設定で生成した成長曲線のレベルごとの値を data/Classes.json に書き出しているようでした。この内容をゲームが起動して画面が出るまでのどこかのタイミングで読み込んで、$dataClasses というグローバル変数に入れているようです。
*1 VXのときは Ruby の Marshal を内部的に使ってたっぽいですね

ということは、この Classes.json を書き換えちゃえばいいんじゃないのと一瞬思ったんですが、それをやるとたぶんゲームエディタのDBで職業タブをいじるたびに元に戻っちゃいそうなんですよね。試してないけど。なら、その json を読み込んだあとで画面に出るまでのどこかのタイミングで $dataClasses を上書きしちゃえばいいじゃん、という方針で書き始めました。

処理の流れは?

で、いろいろ試行錯誤しつつ調べた処理の流れは以下の通り(関係ありそうなところ抜粋)。

Main.onEffekseerLoad() から SceneManager.run(Scene_Boot)。

Scene_Boot.create() から DataManager.loadDatabase()。

DataManager.loadDatabase() から、DataManager._databaseFiles で定義されているとおりに data/*.json を読み込んでそれぞれの内容をグローバル変数に入れる。

いろいろあって、Scene_Boot.start() で、戦闘テストの場合はそれ用の準備 DataManager.setupBattleTest() をして、テストプレイの場合は Scene_Boot.startNormalGame() が呼ばれ、その中でゲーム開始時の準備 DataManager.setupNewGame() 。

setup*() したらその中でもう SceneManager.goto(次のシーン) してしまっているので、プラグインの中ではこの両者の処理の前に、$dataClasses の中身を書き換えちゃえばOK。

ということはたとえば、

const _DataManager_setupNewGame = DataManager.setupNewGame;
DataManager.setupNewGame = function() {
    // ここでいい感じに $dataClasses の中身を上書き
    _DataManager_setupNewGame.apply(this);
};

という感じかなということで動かしたら、まぁなんとかいけそうです。

画像1

↑戦闘テストのスクショをとるまえにおおなめくじに殴られたので少し減っている/まりょくときまほうぼうぎょとかうんのよさは今回は使わないのであとで非表示にする予定。

あとはレベルが上がったときに実際その通りになってくれるかというのはテストしないといけないですね。そこまでうまくいったらこれもプラグインとして公開する、かも。まぁ需要があるかないかとかあんまりひとりで考えててもしょうがないので公開しちゃうか。


この記事が気に入ったらサポートをしてみませんか?