市販RPGでよくあるスキルのプラグイン化の考察
はじめに
この記事は、ツクールフォーラム アドベントカレンダーの16日目の記事となります。
内容は、市販のRPGではよく見かけるのに、ツクールMV/MZのプラグインでは寡聞にして見かけない、そんな要素を集め、「仮に僕が実現するなら、どういう風にする」という考察を交えて紹介しています。
世界樹の迷宮Xにはまったことがこの記事を書くきっかけだった
ここ数か月、僕は世界樹の迷宮Xを現在進行形でプレイしていました。
このゲームにはたくさんのスキルがあり、パッシブスキルも数多いです。僕が気に入ったスキルはいくつもあるけれど、RPGツクールMZのイベントコマンドやプラグインでそれらを再現したいと思いました。そこでいくつかめぼしい点を書きます。
1.一定確率で敵を即死させるパッシブスキル
主な例では、Wizardryの忍者の首はねが挙げられますね。その他にも、どれだけHPが残ってても、これを受けたら死亡、という技は多くのゲームに採用されています。ドラクエのデーモンスピアや、Wizardyの忍者や世界樹の迷宮Xでのシノビのパッシブスキル「一定確率で敵の首をはねる」というのがあります。
これはスキル効果の「ステート付加」で戦闘不能を付与すれば簡単に実現可能ですが、ひとつ困ったことがあります。HPをゼロにして倒した場合でも、首切りなど「息の根を止める」技で倒した場合も、表示されるメッセージは、一緒です。これでは、即死パッシブで倒したのか、通常攻撃のダメージで倒したのか、分かりません。
即死パッシブで倒した場合だけ別のメッセージ(例:○○の息の根を止めた!)という風にしてみたいものです。これはツクール2000時代からの懸案事項でした。
もしこれを実現するとしたら……
考えられるのは、即死(首はね)専用のステートを新設し、即死効果で戦闘不能になったときは、こちらを付与する、というものです。これが可能なら、各即死のメッセージを何種類も作れます。
ところが、ステートの特徴には、別のステートを有効にするものがありません。強いて挙げるなら、能力値>追加能力値>HP再生率 を-100%にすることくらいでしょうか。
よってプラグインでの実現が望ましいと考えられます。具体的にはステートを即死ステートにしたい場合、例えばメモ欄に
Game_Battler.prototype.addState にて、ステートのメモを参照し、この記述があるステートには、Game_BattlerBase.prototype.deathStateId で定義されたステートを同時に付与する、と言う風にすれば可能になるでしょう。
2.行動が最後になるが効果大の攻撃など
ドラクエ9の「ラストバッター」がこれに該当しますが、世界樹の迷宮Xのヒーローも同じような技を習得します。
まず。これは、TPBでは意味をなしませんが、ターン制の場合は戦略性が増す技になりますね。
もしこれを実現するとしたら……
ターン制で行動順を決める関数は、BattleManager.makeActionOrders です。
この処理の最後に、this._actionBattlers のうち、その技を使うバトラーを取り出し、一番最後に追加することで実現可能になります。
同様の方法で、ターンの一番最初に行動する技(パッシブスキル)も作成可能ですが、こちらはより簡単な方法があるかもしれません。
3.特定の条件を満たしたとき、敵がレアドロップアイテムを落とす
これは世界樹の迷宮Xが採用しており、「敵のステートを○○にした状態で倒せ」「○○属性の攻撃でとどめをさせ」などが多いです。
同様の事例は、ドラクエ9や11でも見かけましたね。特定の敵を特定の技でとどめを刺せ、というクエストが多かった気がします。
もしこれを実現するとしたら……
まず、敵キャラのメモに、どういう倒し方をするとどのアイテムが手に入るかを記述します。これは、アクターが敵を倒した際に、該当するアクター(Game_Actors)のthis._actions配列を確認し、どんな行動で敵を倒したかを確認する必要があるでしょう。(未検証なのでうまくいくか不明ですが)
4.自らの分身を作るスキル
世界樹の迷宮Xでは、一部の職業で、分身や、幻影が現れ、行動を行う、といったことが可能です。最大5人パーティーで、1列あたり3人×2列なので、ひとつ分身を表示する場所があります。
もしこれを実現するとしたら……
デフォルトの戦闘では参加アクターは最大4人ですが、既に埋まってしまっています。よって、パーティーを3人以下にしたり、あるいはプラグインで5人目の表示枠を作ったりする必要があります。
その上での実現方法のひとつを挙げます。
Step.1 分身用の新しいアクターを作成
「そのキャラが分身かどうか」の判定変数をGame_Actorに追加し、そのキャラが本体か分身か分かるようにします。
Step.2 アクターの本体をディープコピーする
通常のコピーはシャローコピーと呼ばれ、分身の状態が変化すると、本体の状態も変化してしまいます。それゆえにディープコピーが必要なのです。例えば以下の書式。
const dupeActor=JsonEx.makeDeepCopy(actor);
これで本体から分身アクターを独立して作成できました。
Step.3 元のアクターをコピーした分身の能力値を設定
名前を「○○の分身」にするなど微調整でいいと思います。
Step.4 分身を戦闘メンバーに追加
バトルメンバーのリストに分身を含めます。具体的には、Game_Party.prototype.battleMembersの処理の最後に、分身アクターを含むことが可能です。
Step5.分身が役割を果たして消える時の処理を追加
分身は「○ターン後に消える」や、「戦闘終了時」などには忘れずにメンバーからはずす必要があります。Step.1で作成した関数で、分身かどうかを判断し、分身の場合、メンバーのリストから分身を忘れず消しましょう。
他にも処理はあるでしょうが、基本的にはこの方針で行けると思います。
5.別のアクターにその戦闘中だけ変身する
これは世界樹にはありませんでしたが、ドラクエのモシャスが有名ですね。そんなに有名なら、プラグイン作者の誰かが既に実現していると思っていましたが、意外にも見つからない。確かにトリッキーなやり方をしないといけない。そのあたりで躓く人が多かったのかもしれません。
もしこれを実現するとしたら……
大体僕だったらこうするでしょう。
Step.1 変更判定用に変数を準備
変身対象になったアクターのIDを表す変数(例えばmutation)をGame_Actorに追加します。変身中でなければ、この変数の値は0であるものとします。
もし変身中の場合、対象となるアクターのIDがこの変数に格納されています。
Step.2 変身する対象をディープコピーしたアクターを導入
前述の通り、変身の対象に影響を与えないためにディープコピーさせます。もちろん、通常の状態も、何らかの変数(Game_Tempクラス推奨)に格納しておく必要があります。
Step.3 変身していることが分かるように微調整
例えば、現在のHP/MPやアクターの名前は、変身前の値に変更したほうがいいでしょう。また、アクターIDについても、変身前の値にすべきです。
Step.4 バトルメンバーの入れ替え
変身前のオリジナルのアクターは、戦闘参加メンバーからはずし、そこに変身したアクターに置き換えるのが賢いと思われます。
Step.5 変身が解けた時の処理を追加
変身が解ける時は(戦闘終了時は必ず)Step.4とは逆に、変身したアクターを消し、そこに本来のアクターを挟みます。
そして、変身対象の変数の値を0にリセットします。
以上は机上の空論レベルなので、実際の作業は、より若干複雑になると思われます。
他にももっとやりやすい方法もあると思われます。
6 戦闘不能の致命傷を受けても一定確率でHP1で踏み止まる
世界樹の迷宮Xにもありましたが、僕の敬愛するMOTHER2にもありました。後者は「ガッツ」というパラメータがあり、その数値が高いほど、踏み止まれる確率が高まります。
もしこれを実現するとしたら……
Game_BattlerBase.prototype.die の最初に処理を追加すれば行けると思われます。具体的には、HP1で踏み止まる場合、Game_BattlerBase.prototype.revive を呼び出せばいいでしょう。
7 使用した側が副作用をこうむるスキル
実は「スキルの副作用プラグイン」で検索すれば、MV版ですが、副作用を付けられるものが見つかります。トリアコンタン様作のSideEffectSkill.jsです。
これを有効活用すれば、より様々な効果が作れそうです。
具体的には……
8 多彩な攻撃範囲
世界樹の迷宮では、敵、味方ともに前列後列があります。通常の武器だと、後列にいたら敵の前列までしか届かない、後列にいると与えるダメージ、被ダメージともに半減、銃や弓はその制限を受けない……などです。MVのプラグインでも、前列後列を分けるプラグインがありましたね。
さて、このような状態なので、効果範囲が「前列か後列全体(=一列)」という技が多くあります。しかしそれ以外に興味深いのが、「メインの敵1体と、その左右にいる敵に若干弱めの攻撃」というスコープがあります。確か同様の範囲指定は、黄金の太陽にもあったと思いますが、こういったスクリプトは寡聞にして知りません。
現状のツクールMZでは、「敵味方全体」や「生存か否かにかかわらず効果有り」といったスコープが新たに導入されました。どうやら開発時にはドラクエでいうところの敵1グループという範囲も検討されたようですが、「敵全体を敵グループと呼んでいるので、何か相応しい名前はないか」と悩まれていたので僕が「種族(英語ではtribe)はいかが」と提案しましたが、もともとそんなに多くの敵が出てこないゲームが多いためか、見送られました。これは僕はRGSS2で必要だったのでスクリプト書きました(ぼくのすむまちVXシリーズに入っているので、ツクールVXをお持ちの方はお手軽にコピペして使ってかまいません、というスタンスでした)ので一度はMVへの移植も検討しましたが、敵の頭数の関係から、種族スコープが恩恵を受けるのは少なそうだな、と思って見送ってきました。
もしこれを実現するとしたら……
新しい効果範囲を追加する試みはMVで既に行われています。MZでは標準搭載になりましたが「生死問わず効果の出るステート」をMVで実現するため、DeadOrAliveItem.js という準公式プラグインがありましたが、これを参考にすれば、いろんな範囲の技が作れそうです。