開発日誌

テクニック

[ テクニック ] [ 素材 ] [ プラグイン/スクリプト ] ダメージ計算式内のスクリプトが自動戦闘で実行されるのを防ぐ

2022-03-21 16:11:50

スキルやアイテムのダメージ計算式内に、ダメージ計算以外のスクリプトを書いた際に、自動戦闘の評価時にもそれが実行されてしまうのを防ぐプラグインを作成しました。

RPGツクールMV/MZの両方に対応しています。

ダメージ計算式の応用テクニック

スキルやアイテムのダメージ計算式にはスクリプトを記述することができ、ダメージ計算式以外の処理をさせることができます。

例えば「体当たり」という、敵に大ダメージを与える代わりに、自分がスタンしてしまうスキルを考えます。

このような、相手にダメージを与えつつ、自分にも何らかの効果を及ぼすようなスキルは、標準では作れません。RPGツクールMZであれば、新たに導入された「直前に行動したアクターのID」や「直前に行動した敵キャラのインデックス」を用いて、コモンイベントでステートを付与することも可能ですが、味方はともかく敵キャラのスキルとしても対応させようとすると、けっこう面倒くさいです。

しかし、RPGツクールMVでも可能で、かつ簡易な方法があります。

それが、ダメージ計算式を応用する方法です。

ダメージ計算式の中はスクリプトが書けるようになっており、かつスキルの使用者がa、対象者がbで表せるようになっています。

通常の使い方としては、a.atkで使用者の攻撃力を取得したり、b.defで対象者の防御力を取得したりするものですが、aやbの実体はGame_ActorやGame_Enemyオブジェクトなので、それらが持つプロパティやメソッドは全て使用することができます。

すなわち、a.addState(10)と書けばスキルの使用者に10番のステートを付与することができますし、a.increaseBuff(4)と書けばスキルの使用者の魔法力を1段階上げることができます。

前述の「体当たり」スキルであれば、

a.addState(13); a.atk * 4

と書くことで、自身の攻撃力の4倍のダメージを相手に与えつつ、代わりに自分が13番のステート(スタン)にかかります。

正攻法ではありませんが、このダメージ計算式にスクリプトを埋め込む方法は、応用技としてよく用いられており、当サイトでも「プラグインなしでムチ攻撃」などの記事で紹介しています。

自動戦闘での問題点

しかし、このダメージ計算式の応用技は自動戦闘の際に問題があります。

アクターや職業、武器の特徴では「特殊フラグ」の「自動戦闘」というのがあり、この特徴が付くと自動的に戦ってくれるようになります。

この自動戦闘の仕様はどういうものかというと、その時に使用可能な全てのスキルを使った時のダメージ量を計算して、ダメージ総量のより多いスキルが選ばれるようになっています。

つまり、最初に全てのスキルに関してダメージ計算を行うため、ダメージ計算式内のスクリプトが実行され、ステート付与など結果を伴うスクリプトの内容が実際に反映されてしまうのです。

本プラグインはこの問題を解消し、自動戦闘におけるダメージ量評価時には、スクリプトの内容が反映されないようになります。

プラグインの実装

具体的にどうやっているのかというと、aにスキルの使用者、bに対象者を代入する際、自動戦闘の評価時には、ツクールのコアスクリプトで定義されているJsonEx.makeDeepCopy()を用いて、使用者と対象者そのものではなく、それのコピーを代入するようにしています。本体ではなくコピーなので、実際のアクターや敵キャラには影響を及ぼしません。

同様にダメージ計算式においては、itemに使用するスキルやアイテム、vに変数が代入されますが、これらもコピーを代入するようにしているので、例えばダメージ計算式内で変数を操作したとしても、実際の変数が変化することはありません。

グローバル変数「inEval」

多くの場合は以上で解決するのですが、場合によってはこれだけでは解決しないケースがあります。

例えば自爆技のように、自分の命と引き換えに、敵に大ダメージを与えるスキルの場合、ダメージ計算式を以下のようにすれば、とりあえず目的は達成することができます。

a.die(); 300

上記の例では、a.die()で使用者を戦闘不能状態にさせつつ、敵に300ポイントのダメージを与えることができます。

ただこれだと、使用者に戦闘不能のステートが付くだけで、死亡時のエフェクトがないため、自爆したことが分かりづらいです。

performCollapse()で死亡時のエフェクトを演出することができるので、ダメージ計算式を下記のようにしてみましょう。

a.die(); a.performCollapse(); 300

これでちゃんと死亡時のエフェクトが出るようになりましたが、自動戦闘にすると評価時にも死亡時のSEが鳴ってしまいます。

本体ではなくコピーを使うことで、ステートの変化が実際に反映されることはなくなりましたが、SEやアニメーションなどはその限りではありません。

というわけで、自動戦闘の評価時か否かを表すグローバル変数「inEval」を定義しました。

inEvaltrueであれば自動戦闘の評価時、falseであれば実際のスキルの使用時となり、ダメージ計算式内で分岐させることができます。

a.die(); !inEval && a.performCollapse(); 300

上記のように書けば、自動戦闘の評価時にはa.performCollapse()が実行されず、実際の使用時にのみ実行されるようになります。

変数名として「inEval」を使っているプラグインとは競合する可能性がありますので、ご注意ください。

質問やアドバイスなどはコメント欄まで、お気軽にお願いします。素材利用条件などについては、このサイトについての「提供素材について」の項目などをご覧ください。

コメント
お名前
コメント
※ 確認画面はありません。